Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

썸네일 서비스 테스트코드 작성 #662

Merged
merged 7 commits into from
Sep 22, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package codezap.template.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;

import java.util.List;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import codezap.category.repository.CategoryRepository;
import codezap.fixture.CategoryFixture;
import codezap.fixture.MemberFixture;
import codezap.fixture.TemplateFixture;
import codezap.global.DatabaseIsolation;
import codezap.global.exception.CodeZapException;
import codezap.member.repository.MemberRepository;
import codezap.template.domain.SourceCode;
import codezap.template.domain.Thumbnail;
import codezap.template.repository.SourceCodeRepository;
import codezap.template.repository.TemplateRepository;
import codezap.template.repository.ThumbnailRepository;

@SpringBootTest
@DatabaseIsolation
class ThumbnailServiceTest {
zangsu marked this conversation as resolved.
Show resolved Hide resolved

@Autowired
private MemberRepository memberRepository;

@Autowired
private CategoryRepository categoryRepository;

@Autowired
private TemplateRepository templateRepository;

@Autowired
private SourceCodeRepository sourceCodeRepository;

@Autowired
private ThumbnailRepository thumbnailRepository;

@Autowired
private ThumbnailService sut;

@Nested
@DisplayName("썸네일 생성")
class CreateThumbnail {

@Test
@DisplayName("썸네일 생성 성공")
void createThumbnailSuccess() {
var member = memberRepository.save(MemberFixture.getFirstMember());
var category = categoryRepository.save(CategoryFixture.getFirstCategory());
var template = templateRepository.save(TemplateFixture.get(member, category));
Comment on lines +58 to +60
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복되는 코드 private 메서드로 추출해볼까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거는 일부러 분리하지 않았는데요, 전에 켬미와 얘기했던 @beforeeach를 사용하지 않는 이유에 동의했기 때문입니다!
물론 private 메서드로 분리하는 것은 @beforeeach보다는 덜하겠지만 그래도 어떤 객체들이 저장되어 있는지 테스트 코드 안에서 바로 확인할 수 있는게 보다 명확하게 알 수 있지 않을까 싶어서 분리하지 않았습니다.
또한 코드의 길이가 길지 않아 테스트 코드의 가독성을 해친다는 느낌도 없는 것 같은데 몰리의 의견은 어떤가요?

Copy link
Contributor

@jminkkk jminkkk Sep 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BeforeEach를 사용하지 않았던 이유가 특정 테스트만 조회할 때 @BeforeEach 보지 못하고 이해하지 못할까봐로 저는 알고 있는데 같은 이유가 맞나요?

그렇다면, private 메서드는 @BeforeEach과 다르게 메서드 안에서 "선언"을 해주기 때문에 보는 사람이 충분히 메서드 내에서 파악할 수 있을 것이라고 생각해요.
또 private 메서드를 사용하더라도 이름을 명확하게 설정해주면 메서드를 정말 확인하지 않아도 파악할 수 있을 것 (레벨 1 네오 강의 의견처럼요) 이라고도 생각해요.

var sourceCode = sourceCodeRepository.save(new SourceCode(template, "Filename 1", "Content 1", 1));

sut.createThumbnail(template, sourceCode);
var actual = thumbnailRepository.fetchByTemplate(template);

assertAll(
() -> assertThat(actual.getId()).isEqualTo(1L),
() -> assertThat(actual.getTemplate()).isEqualTo(template),
() -> assertThat(actual.getSourceCode()).isEqualTo(sourceCode)
);
}
}

@Nested
@DisplayName("썸네일 조회")
class GetByTemplate {

@Test
@DisplayName("썸네일 조회 성공")
void getByTemplateSuccess() {
var member = memberRepository.save(MemberFixture.getFirstMember());
var category = categoryRepository.save(CategoryFixture.getFirstCategory());
var template = templateRepository.save(TemplateFixture.get(member, category));
var sourceCode = sourceCodeRepository.save(new SourceCode(template, "Filename 1", "Content 1", 1));
thumbnailRepository.save(new Thumbnail(template, sourceCode));

var actual = sut.getByTemplate(template);

assertAll(
() -> assertThat(actual.getId()).isEqualTo(sourceCode.getId()),
() -> assertThat(actual.getTemplate()).isEqualTo(template),
() -> assertThat(actual.getSourceCode()).isEqualTo(sourceCode)
);
}

@Test
@DisplayName("썸네일 조회 실패: 해당하는 썸네일이 없는 경우")
void getByTemplateFailWithWrongID() {
var member = memberRepository.save(MemberFixture.getFirstMember());
var category = categoryRepository.save(CategoryFixture.getFirstCategory());
var template = templateRepository.save(TemplateFixture.get(member, category));

assertThatThrownBy(() -> sut.getByTemplate(template))
.isInstanceOf(CodeZapException.class)
.hasMessage("식별자가 " + template.getId() + "인 템플릿에 해당하는 썸네일이 없습니다.");
}
}

@Nested
@DisplayName("썸네일 삭제")
class DeleteByTemplateIDs {

@Test
@DisplayName("썸네일 삭제 성공: 1개의 썸네일 삭제")
void deleteByTemplateSuccessWithOneThumbnail() {
var member = memberRepository.save(MemberFixture.getFirstMember());
var category = categoryRepository.save(CategoryFixture.getFirstCategory());
var template1 = templateRepository.save(TemplateFixture.get(member, category));
var sourceCode1 = sourceCodeRepository.save(new SourceCode(template1, "Filename 1", "Content 1", 1));
var savedThumbnail1 = thumbnailRepository.save(new Thumbnail(template1, sourceCode1));
var template2 = templateRepository.save(TemplateFixture.get(member, category));
var sourceCode2 = sourceCodeRepository.save(new SourceCode(template2, "Filename 2", "Content 2", 1));
var savedThumbnail2 = thumbnailRepository.save(new Thumbnail(template2, sourceCode2));

sut.deleteByTemplateIds(List.of(template1.getId()));
var actual = thumbnailRepository.findAll();

assertThat(actual).hasSize(1)
.containsExactly(savedThumbnail2)
.doesNotContain(savedThumbnail1);
}

@Test
@DisplayName("썸네일 삭제 성공: 2개의 썸네일 삭제")
void deleteByTemplateSuccessWithTwoThumbnail() {
var member = memberRepository.save(MemberFixture.getFirstMember());
var category = categoryRepository.save(CategoryFixture.getFirstCategory());
var template1 = templateRepository.save(TemplateFixture.get(member, category));
var sourceCode1 = sourceCodeRepository.save(new SourceCode(template1, "Filename 1", "Content 1", 1));
var savedThumbnail1 = thumbnailRepository.save(new Thumbnail(template1, sourceCode1));
var template2 = templateRepository.save(TemplateFixture.get(member, category));
var sourceCode2 = sourceCodeRepository.save(new SourceCode(template2, "Filename 2", "Content 2", 1));
var savedThumbnail2 = thumbnailRepository.save(new Thumbnail(template2, sourceCode2));

sut.deleteByTemplateIds(List.of(template1.getId(), template2.getId()));
var actual = thumbnailRepository.findAll();

assertThat(actual).isEmpty();
}

@Test
@DisplayName("썸네일 삭제 성공: 존재하지 않는 경우")
void deleteByTemplateFailWithWrongID() {
var member = memberRepository.save(MemberFixture.getFirstMember());
var category = categoryRepository.save(CategoryFixture.getFirstCategory());
var template = templateRepository.save(TemplateFixture.get(member, category));
var sourceCode = sourceCodeRepository.save(new SourceCode(template, "Filename 1", "Content 1", 1));
var savedThumbnail = thumbnailRepository.save(new Thumbnail(template, sourceCode));
var nonExistentID = 100L;

sut.deleteByTemplateIds(List.of(nonExistentID));
var actual = thumbnailRepository.findAll();

assertThat(actual).hasSize(1)
.containsExactly(savedThumbnail);
}
}
}