스프링 부트에서 테스트를 진행해 보자!
스프링 에서는 @SpringBootTest 을 이용해 테스트를 진행할 수 있다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
다음과 같은 의존성을 추가해야 테스트를 진행할 수 있다.
테스트를 해보기 위해 다음과 같이 hello 요청에 대한 처리를 하는 컨트롤러와 서비스를 작성해보자
@SpringBootTest
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleControllerTest {
@Test
public hello() {
}
}
먼저 가장 기본적인 테스트 코드이다. 따로 빈설정을 해주지 않아도 @SpringBootApplication이 알아서 해준다.
Mock
@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())
.andExpect(content().string("ny"))
.andDo(print());
}
}
먼저 MockMvc환경으로 테스트를 해보자. Mock 환경은 내장톰캣이 구동이 안되며
@MockBean을 이용해 서블릿 컨테이너를 띄우지 않고 dispatcherServlet에 요청을 보낸 것 처럼 테스트할 수 있다.
RANDON_PORT, DEFINED_PORT
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SampleControllerTest {
@Autowired
TestRestTemplate testRestTemplate; //내장톰캣서버에 요청 보내서 확인.. 서비스단까지감
@Test
public void hello() throws Exception{
String result =testRestTemplate.getForObject("/hello", String.class);
assertThat(result).isEqualTo("hellonewny");
}
}
다음은 랜덤포트로 지정하여 TestRestTemplate를 이용한 방법이다.
Mock환경이 아니라 랜덤포트를 이용해 실제로 컨테이너가 구동되는 환경이다.
모든 빈이 다 등록되어 테스트 환경이 무거울수도 있다.
부분적으로 Mock 이용
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class SampleControllerTest {
@Autowired
TestRestTemplate testRestTemplate;
@MockBean
SampleService mockSampleService; //컨트롤러만 테스트, 샘플컨트롤러빈을 여기서 만든 목빈으로 교체됨
@Test
public void hello() throws Exception{
when(mockSampleService.getName()).thenReturn("newny");
String result =testRestTemplate.getForObject("/hello", String.class);
assertThat(result).isEqualTo("hellonewny");
}
}
서비스까지 가지 않고 컨트롤러만 테스트해보고 싶다면 다음과 같이 SampleService 를 이용할 수 있다.
ApplicationContext에 SampleController빈이 MockBean으로 등록된다.
WebTestClient
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class SampleControllerTest {
@Autowired
WebTestClient webTestClient;
//스프링5에서 추가됨. 요청을 보내고 기다리는게 아닌 요청이오면 콜백 실행, async하게 실행됨
@MockBean
SampleService mockSampleService;
@Test
public void hello() throws Exception{
when(mockSampleService.getName()).thenReturn("ny");
webTestClient.get().uri("/hello").exchange()
.expectStatus().isOk()
.expectBody(String.class).isEqualTo("hellony");
}
}
기존테스는 요청을 보내고 응답을 기다리는 sync방식이였다면 WebTestClient는 async하게 실행된다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
다음과 같은 의존성을 추가해야 WebTestClient를 이용할 수 있다.
슬라이싱테스트
모든빈을 다 등록하는 것이 아닌, 테스트 할 Bean만 등록하여 슬라이싱 테스트를 할 수 있다.
@RunWith(SpringRunner.class)
@WebMvcTest(SampleController.class) // 웹과 관련된 애들만 등록됨
public class SampleControllerTest {
@MockBean
SampleService mockSampleService;
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception{
when(mockSampleService.getName()).thenReturn("ny");
mockMvc.perform(get("/hello"))
.andExpect(content().string("hellony"));
}
}
@WebMvcTest 을 이용해 테스트할 컨트롤러를 지정해준다. @WebMvcTest는 웹과 관련된 컨트롤러 들만
빈으로 등록되고 서비스나 레파지토리는 빈으로 등록되지 않는다.
따라서 @MockBean으로 SampleService 서비스빈을 등록해주어야 한다.
또한, WebMvcTest 는 반드시 MockMvc 로 테스트 해야한다.
테스트유틸 - OutputCapture
@RestController
public class SampleController {
Logger logger = LoggerFactory.getLogger(SampleController.java)
@Autowired
private SampleService sampleService;
@GetMapping("/hello")
public String hello() {
logger.info("ny")
return "hello " + sampleService.getName();
}
}
@RunWith(SpringRunner.class)
@WebMvcTest(SampleController.class)
public class SampleControllerTest {
@MockBean
SampleService mockSampleService;
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception{
when(mockSampleService.getName()).thenReturn("ny");
mockMvc.perform(get("/hello"))
.andExpect(content().string("hellony"));
assertThat(outputCapture.toString()).contains("ny");
}
}
outputCapture 테스트 유틸을 이용하면 콘솔에 찍히는 로그까지 테스트 할 수 있다.