자라선

14. Test 본문

Develop/Spring Boot

14. Test

자라선 2020. 7. 27. 16:26

스프링 테스트 의존성 추가

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

테스트 코드 기본 폼

@RunWith(SpringRunner.class)

@SpringBootTest

 

@SpringBootTest 어노테이션은 @SpringBootApplication 어노테이션을 찾아가 모든 자동설정을 실행하여

모든 bean 스캔과 테스트용 ApplicationContext에 등록한다.


MockMvc 사용 (통합 테스트)

3가지의 방법중 가장 쉬운 방법으로 서블릿 컨테이너를 생성하지 않고 디스패처 서블릿을 mocking 을 하여

비슷한 역할을 해준다. 그러나 mocking를 하여 생성된 디스패처 서블릿을 사용하려면 MockMvc 클라이언트를 사용해야한다.

@SpringBootTest에서 WebEnvironment의 값이 MOCK 이어야한다.(default = MOCK)

@AutoConfigureMockMvc 어노테이션을 작성하고 MockMvc를 주입받아 사용.

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
class SampleControllerTest {
 
    @Autowired
    MockMvc mockMvc;
 
    @Test
    void hello() throws Exception{
        mockMvc.perform(get("/hello"))
                .andExpect(status().isOk())
                .andExpect(content().string("hello taehyun"))
                .andDo(print());
    }
}

TestRestTemplate 를 사용 (통합 테스트)

MockMvc 와 다르게 @SpringBootTestwebEnvironment 값을 RANDOM_PORT로 준다면 서블릿 컨테이너가 실행되며 이렇게 띄어진 톰캣에 직접 요청하여 테스트를 진행.

testRestTemplategetForObject를 통해서 Rest 리턴값을 받아 assertThat으로 확인

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SampleControllerTest {
 
    @Autowired
    TestRestTemplate testRestTemplate;
 
    @Test
    void hello() throws Exception{
        String result = testRestTemplate.getForObject("/hello", String.class);
        assertThat(result).isEqualTo("hello taehyun");
    }
}

특정 부분만 테스트를 하기 위해서는 @MockBean 어노테이션을 사용하여 ApplicationContextbean으로 등록된 동일 bean을 교체하여 테스트를 진행할 수 있다.

when() 를 사용해 조건을 준다. 아래같은 경우 service에서 getName 요청한다면 반환값을 "thkong"로 반환되도록 교체

import static org.mockito.Mockito.when;
…..
@MockBean
SamepleService mockSamepleService;
 
@Test
public void hello() throws Exception{
    when(mockSamepleService.getName()).thenReturn("thkong");

비동기화 방식 테스트 (통합 테스트)

웹 플럭스를 사용하여 테스트를 진행 할 수 있다.

일반적인 테스트는 동기화 방식으로 요청 후 응답까지 기다려야하지만 웹 플럭스를 사용해 비동기 방식으로 한다면 요청 후 콜백이 돌아와 RestAPI의 테스트를 효율적으로 할 수 있다.

 

의존성 정의

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

코드

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.mockito.Mockito.when;
 
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SampleControllerTest {
 
    @Autowired
    WebTestClient webTestClient;
 
    @MockBean
    SamepleService mockSamepleService;
 
    @Test
    public void hello() throws Exception{
        when(mockSamepleService.getName()).thenReturn("thkong");
        webTestClient.get().uri("/hello").exchange().expectStatus().isOk()
                .expectBody(String.class).isEqualTo("hello thkong");
    }
}

슬라이스 테스트

통합 테스트 처럼 전체적으로 테스트 하지 않는다면 특정 부분만 정의하여 테스트를 진행할 수 있다.

·        @JsonTest

·        @WebMvcTest

·        @WebFluxTest

·        @DataJpaTest


특정 컨트롤러 만 테스트

@WebMvcTest 어노테이션을 정의하고 특정 컨트롤러의 클래스를 작성한 후

MockMvc @Autowiredbean을 주입받아서 사용해야한다.

하지만 @Component로 정의된 @Service@Repository 등의 어노테이션은 bean으로 생성되지 않기 때문에

@MockBean으로 특정 조건에 부합했을때의 결과값으로 정의해줘야한다.

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
 
@RunWith(SpringRunner.class)
@WebMvcTest(SampleController.class)
class SampleControllerTest {
 
    @MockBean
    SamepleService mockSamepleService;
 
    @Autowired
    MockMvc mockMvc;
 
    @Test
    public void hello() throws Exception{
        when(mockSamepleService.getName()).thenReturn("thkong");
 
        mockMvc.perform(get("/hello"))
                .andExpect(content().string("hello thkong"))
                .andDo(print());
    }
}

@OutputCapture

System.out.println 이나 logger로 출력된 모든 콘솔 로그를 뽑아서 테스트 할 수 있다.

Junit 라이브러리의 @Rule를 사용한다.

    @Rule
    OutputCapture outputCapture;
 
        assertThat(outputCapture.toString())
                .contains("Controller Request")
                .contains("Service Request");

 

'Develop > Spring Boot' 카테고리의 다른 글

16. Spring MVC  (0) 2020.07.27
15. devtools  (0) 2020.07.27
13. Logging  (0) 2020.07.27
12. Profile  (0) 2020.07.27
11. 외부설정  (0) 2020.07.27
Comments