JAVA/TEST

@SpringBootTest와 @WebMvcTest, @MockBean 그리고 WebClinet까지

gracelove91 2020. 1. 29. 22:07

코드

  • 다음과 같은 컨트롤러와 서비스가 있다.

SampleController

@RestController
public class SampleController {

    private SampleService sampleService;

    public SampleController(SampleService sampleService) {
        this.sampleService = sampleService;
    }

    @GetMapping("/hello")
    public String hello() {
        return "hello " + sampleService.getName();
    }
}

SampleService

  @Service
  public class SampleService {
      public String getName() {
          return "gracelove";
      }
  }
  • localhost:8080/hello로 요청을 보내면 "hello gracelove" 를 응답값으로 되돌려준다.

테스트

MockMvc를 이용한 테스트

  • @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)

    • 디폴트값이다. 괄호 안에 옵션안주면 자동적용된다.

    • 내장톰캣 실행안시킨다.

    • MockMvc 빈으로 등록 안시킨다

    • 따라서 MockMvc를 이용하기 위해서는 @AutoConfigureMockMvc 가 필요하다

      @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
      @AutoConfigureMockMvc
      class SampleControllerTest {
      
      @Autowired
      private MockMvc mockMvc;
      
      @Test
      void hello() throws Exception {
          mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
                  .andExpect(status().isOk())
                  .andExpect(content().string("hello gracelove"))
                  .andDo(print());
      }
      }

TestRestTemplate 을 이용한 테스트

  • RANDOM_PORT옵션주면 내장톰캣 실행한다.

    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    class SampleControllerTest2 {
    
    @Autowired
    TestRestTemplate testRestTemplate;
    
    @Test
    void hello() {
    
        String result = testRestTemplate.getForObject("/hello", String.class);
        assertThat(result).isEqualTo("hello gracelove");
    }
    }

WebTestClient를 이용한 테스트

  • non-blocking 기반의 클라이언트다.

  • 이용하기 위해서는 pom.xml 에서 다음과 같이 의존성을 추가해주자.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SampleControllerTest3 {

    @Autowired
    WebTestClient webTestClient;

    @Test
    void hello() {
        webTestClient.get().uri("/hello").exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("hello gracelove");
    }
}

@WebMvcTest와 @MockBean을 이용한 테스트

  • 위 테스트코드들은 모두 통합테스트다. 기본적으로 @SpringBootTest 어노테이션을 사용하면 스프링이 관리하는 모든 빈을 등록시켜서 테스트하기 때문에 무겁다.

  • 하지만 @WebMvcTest는 web 레이어 관련 빈들만 등록하므로 비교적 가볍다.

  • web레이어 관련 빈들만 등록되므로 Service는 등록되지않는다. 따라서 가짜로 만들어줄 필요가 있다 (@MockBean)

    @WebMvcTest(SampleController.class)
    class SampleControllerTest4 {
    
     @Autowired
     MockMvc mockMvc;
    
     @MockBean
     SampleService mockSampleService;
    
     @Test
     void hello() throws Exception {
         when(mockSampleService.getName()).thenReturn("gracelove");
    
         mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
                 .andDo(print())
                 .andExpect(status().isOk())
                 .andExpect(content().string("hello gracelove"));
     }
    }

깃헙 : https://github.com/gracelove91/springboot-with-whiteship/tree/d3a19620bd70d5dd4af4ffa14fcc9408bef3ed29