티스토리 뷰

반응형

Spring boot test, junit5, mockito 사용에 대한 정리

Spring boot 2.2부터는 기본으로 Junit5모듈을 사용하게된다.

Junit5란?

Junit 4는 단일 모듈이였던 반면, JUnit 5는 크게 Junit Jupiter, JUnit plateform,  JUnit Vintage모듈로 구성되어진다. 아래는 그구성에 대한 설명이다.

Junit Platform : 테스트들을 실행하기 위한 뼈대이다. 테스트를 발견하고 테스트 계획을 생성하는 TestEngine 인터페이스를 가지고 있다. Platform은 TestEngine을 통해서 테스트를 발견하고, 실행하고, 결과를 보고한다. 또한 콘솔출력, 각종 IDE들의 연동을 보조하는 역할을 한다.

Junit Jupiter : TestEngine의 실제 구현체는 별도 모듈의 역할을 한다. 모듈 중 하나가 jupiter-engine이다. 이 모듈은 jupiter-api를 사용해서 작성한 테스트 코드를 발견하고 실행합니다. Jupiter API는 JUnit 5에 새롭게 추가된 테스트 코드용 API로서, 개발자는 Jupiter API를 사용해서 테스트 코드를 작성할 수 있다. Junit 5버전 테스트를 작성할 때 사용된다.

Junit Vintage : 기존에 JUnit 4 버전으로 작성한 테스트 코드를 실행할 때에는 vintage-engine 모듈을 사용한다. 만약 사용하지 않는다면 의존성을 제거할 수 있다.

Junit 5로 인해 기존에 Spring boot 2.0이전에 사용하던 어노테이션들을 변경을했는데 왜 변경했는지에 대해 간단히 정리를 해봤다. 아래는 개인적으로 스프링 부트 2.2이전에 테스트를 할 때 설정했던방식과 2.2 이후에 설정했던 어노테이션을 정리한것이다. 저는 주로 MVC테스트, 단위테스트, 통합테스트위주로 작성합니다.

버전 Spring MVC 테스트 단위 테스트(Mockito) Spring 통합테스트
Spring boot 2.2 이전 @RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest
Spring boot 2.2 이후 @WebMvcTest @ExtendWith(MockitoExtension.class) @SpringBootTest

아래는 어노테이션 변경이유에 대한 내용을 간단하게 정리해봤다.

Spring MVC 테스트

2.2 이전에는 @RunWith(MockitoJUnitRunner.class) 과 MockMvcBuilders를 이용해 가볍게 필요한 빈들만 올려 mvc테스트를 했었다. 그 이후에 WebMvcTest 를 알게되었는데 딱 내가원하던 어노테이션이다. MockMvcBuilders는 필터, resolver등을 설정하기가 까다로웠다. 이 WebMvcTest 는 Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, WebMvcConfigurer, and HandlerMethodArgumentResolver을 스프링 빈으로 올리게된다. @SpringBootTest 어노테이션을올리는것보다 훨씬 가볍게 테스트를 진행할 수 있다. 이 어노테이션은 2.2이전에 존재했던것같다. 간단한 mvc 단위 테스트 예제를 만든다면 아래와 같을 수 있다.

@WebMvcTest(MemberController.class)
class MemberControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private MemberService memberService;

    @Test
    void getMember() throws Exception {
        // given

        given(memberService.getMember(anyLong()))
                .willReturn(new Member(1L, "test"));
        // when
        // then
        mockMvc.perform(get("/members/{id}", 1))
                .andDo(print())
                .andExpect(status().isOk());
    }
}

단위 테스트

@RunWith(MockitoJUnitRunner.class)를 이용했는데. Junit 5부터는 좀더 강력한 확장어노테이션인 ExtendWith를 사용한다. 그래서 @ExtendWith(MockitoExtension.class) 어노테션이 대체하게 되었다. 간단한 service 단위 테스트 예제를 만든다면 아래와 같을 수 있다.

@ExtendWith(MockitoExtension.class)
class MemberServiceTest {

    @InjectMocks
    private MemberService memberService;

    @Mock
    private MemberRepository memberRepository;

    @Test
    public void getMember(){
        // given
        given(memberRepository.findById(anyLong()))
                .willReturn(new Member(1L, "test"));
        // when
        Member member = memberService.getMember(1L);
        // then
        assertEquals(1L, member.getId());
        assertEquals("test", member.getName());
    }
}

Spring 통합테스트

마찬가지로 @RunWith(SpringRunner.class)도 @ExtendWith(SpringExtension.class)로 변경했다. Spring extension은 @SpringBootTest안에들어 있기 때문에 따로 선언할필요가 없다. SpringExtension은 Spring TestContext Framework를 JUnit 5의 Jupiter 프로그래밍 모델에 통합하는 역할을 한다. 간단한 mvc 통합 테스트 예제를 만든다면 아래와 같을 수 있다.

@SpringBootTest
class MemberIntegrationControllerTest {

    private MockMvc mockMvc;

    @BeforeEach
    public void setUp(WebApplicationContext webApplicationContext) {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .build();
    }

    @Test
    void getMember() throws Exception {
        // given
        // when
        // then
        mockMvc.perform(get("/members/{id}", 1))
                .andDo(print())
                .andExpect(status().isOk());
    }
}

위와같이 사용하게된다면 Spring boot starter test에서 더이상 junit-vintage-engine 모듈을 사용하지 않아도 되니 제거할 수있다.

testImplementation("org.springframework.boot:spring-boot-starter-test") {
            exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
}

관련소스 깃허브

참고

반응형

'Back-End > Spring' 카테고리의 다른 글

Spring REST Docs 란?  (1) 2020.06.01
Spring boot 로깅  (0) 2020.02.02
Spring 멀티 모듈 구성  (0) 2019.10.21
Spring Batch Example 3 - 청크 지향 프로세싱  (1) 2019.05.26
Spring Batch Example 2 - 간단한 Job만들기  (0) 2019.05.02
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함