본 글은 백기선님의 스프링부트 개념과 활용강좌를 수강하며 정리한 내용입니다.
그동안 테스트코드를 작성하는 것에 대한 막연함이 있었는데, 이번 포스트를 통해 효율적으로 mvc패턴에 대한 테스트를 진행할 수 있는 방법에 대해 정리한다.
먼저 테스트를 위해서 다음과 같은 의존성주입이 선행되어야한다 .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
해당 방법은 내장톰캣을 구동하지 않고 테스트하는 방식이다.
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) // 서블릿 컨테이너를 테스트용으로 띄우지 않고 테스트 가능
@AutoConfigureMockMvc
public class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().isOk()) //MockMvcResultMatchers에서 임폴트
.andExpect(content().string("hello minsik"))
.andDo(print());
}
위와같은 방식으로 URL요청을 실제로 보내어 테스트를 할 수 있다. 프린트 되어 나온 결과는 다음과 같다.
MockHttpServletRequest:
HTTP Method = GET
Request URI = /hello
Parameters = {}
Headers = {}
Body = null
Session Attrs = {}
Handler:
Type = web.ecoveloper.sample.SampleController
Method = public java.lang.String web.ecoveloper.sample.SampleController.hello()
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/plain;charset=UTF-8], Content-Length=[12]}
Content type = text/plain;charset=UTF-8
Body = hello minsik
Forwarded URL = null
Redirected URL = null
Cookies = []
이곳에 있는 거의 모든 값들에 대하여 테스트 Assertion을 실행할 수 있다.
@SpringBootTest의 설정을 Random Port로 변경해주면 실제 서블릿 컨테이너를 띄워 테스트를 진행할 수 있으며, 그 중 하나인 restTemplate를 활용해 본다.
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SampleControllerTest2 {
@Autowired
TestRestTemplate testRestTemplate;
@MockBean // 실제 서블릿 컨테이너의 빈객체를 Mocking이 가능한 테스트용 빈객체로 교체할 수 있다.
SampleService mockSampleService;
@Test
public void hello() throws Exception {
when(mockSampleService.getName()).thenReturn("ecovel");
String result = testRestTemplate.getForObject("/hello", String.class);
Assert.assertThat(result, Matchers.is("hello ecovel") );
}
}
WebTestClient를 활용하기 위해서는 다음과 같은 디펜던시를 추가해주어야 한다. WebTestClient는 restTemplate와 달리 Asyncronous한 형태로 활용할 수 있다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux </artifactId>
</dependency>
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SampleControllerTest3 {
@Autowired
WebTestClient webTestClient;
@MockBean
SampleService mockSampleService;
@Test
public void hello() throws Exception {
when(mockSampleService.getName()).thenReturn("ecoveloper");
webTestClient.get().uri("/hello").exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("hello ecoveloper");
}
}