테스트 코드 - 문서요약프로젝트

김광훈·2022년 5월 23일
0

문서요약프로젝트

목록 보기
3/3

테스트 코드 - 문서 요약 프로젝트

본 글은 문서 요약 프로젝트의 테스트 코드를 작성하며 깨닫고 공부한바에 대해 지속적으로 업데이트될 예정입니다.

개요

프로젝트를 진행하며 외부 API와 통신하는 메소드를 만들었지만, 해당 메소드가 정말 제대로 동작하는지에 대해 의문이 들기 시작해 테스트 코드를 작성하기로 결심하였다.
단위테스트를 지향하고 있으며, 스프링 컨테이너를 띄우는 통합테스트는 지양하고 있습니다.
junit5와 Mockito 등의 라이브러리를 사용하여 테스트 코드를 작성하였습니다.

Mockito을 이용한 단위테스트

JPA Repository와 같이 인터페이스로 이루어진 경우 구현체가 존재하지 않기 때문에 직접 의존성 주입하는데 어려움이 있어 단위테스트하는 것에 어려움을 겪고 있는 중에, Mockito에 대해서 알게 되었고 가짜(Mock)로 객체를 주입시켜줌으로서 단위테스트를 가능하게 만들었다.
즉, Mockito란 개발자가 동작을 직접 제어할 수 있는 가짜(Mock) 객체를 지원하는 테스트 프레임워크이다.

Mockito 사용법

  • Mock 객체 주입
@Mock : Mock 객체를 만들어 반환해주는 어노테이션
@Spy : Stub하지 않은 메소드들은 원본 메소드 그대로 사용하는 어노테이션
@InjectMocks : @Mock 또는 @Spy로 생성된 가짜 객체를 자동으로 주입시켜주는 어노테이션

예를 들어 ArticleService 대한 단위 테스트를 작성하고자 할때, ArticleRepository를 사용하고 있다면 @Mock 어노테이션을 통해 가짜 ArticleRepository를 만들고, @InjectMocks를 통해 ArticleService에 이를 주입할 수 있다.

  • Stub로 결과 처리
    Mock은 가짜 객체(Mock Object)이기 때문에, 어떤 결과를 반환하라고 정해진 답변을 준비해야 한다. 이러한 답변을 준비하는데 도움을 주는 stub메소드를 제공한다
doReturn() : Mock 객체가 특정한 값을 반환해야 하는 경우
doNothing() : Mock 객체가 아무 것도 반환하지 않는 경우(void)
doThrow() : Mock 객체가 예외를 발생시키는 경우
  • Mockito와 Junit의 결합
    Junit5에서 Mockito를 사용하기 위해서는 아래와 같은 클래스 어노테이션을 붙여줘야 한다.
@ExtendWith(MockitoExtension.class)

ArticleService 단위 테스트

  • ArticleService
    public Article setArticle(GetArticleRequestDto requestDto) {
        Article article = new Article(requestDto);
        return articleRepository.save(article);
    }

ArticleService 중 가장 간단한 setArticle 메소드를 단위테스트 해보겠다.

  • 단위 테스트 준비
//@ExtendWith(SpringExtension.class) //SpringContainer를 로드하므로 Test 객체에 @Autowired를 통한 Bean 의존성을 주입할 수 있습니다.
@ExtendWith(MockitoExtension.class) //SpringContainer를 로드하지 않고 테스트를 위한 기능만 제공합니다.
class ArticleServiceTest {

	@Mock //repository bean에 의존하지 않고 테스트 가능
    private ArticleRepository articleRepository;

    private MockMvc mockMvc;

    @InjectMocks //@Mock으로 선언된 가짜 객체들을 의존한 객체 생성 가능
    private ArticleService articleService;

}

ArticleService의 setArticle메소드가 의존하는 객체는 ArticleRepository이기 때문에, @Mock으로 ArticleRepository 가짜 객체를 생성해주고, ArticleService에 @InjectMocks로 자동으로 주입시켜 주었다.

  • 원문 저장 성공 테스트
@Test
void 오리지널_본문_저장이_제대로_동작하는지_확인() {
//given
GetArticleRequestDto requestDto = new GetArticleRequestDto();
requestDto.setArticleOriginal("test");

Article article = new Article();
article.setId(1L);
article.setArticleOriginal("test");

doReturn(article).when(articleRepository).save(any(Article.class));

//when
Article result = articleService.setArticle(requestDto);

//then
Assertions.assertThat(result.getArticleOriginal()).isEqualTo(requestDto.getArticleOriginal());
}

Mock은 가짜 객체이기 때문에 articleRepository.save가 실행되었을 때 나올 결과에 대해 미리 작성해줘야 한다. 그리고 any()의 안에는 들어갈 클래스를 명시해주는 것이 좋다.
결과적으로 articleService에서 setArticle을 실행해서 얻은 결과 값과 입력한 값과 동일함으로 테스트 통과가 된다.

앞으로 계속 추가적으로 테스트 코드 관련하여 작성할 예정입니다.

참조

[Spring] JUnit과 Mockito 기반의 Spring 단위 테스트 코드 작성법 (3/3)
SpringBoot Service/Repository 단위 테스트 _ Jimin's Daddy

profile
잘 부탁드려요

0개의 댓글