Test
우리는 Spring-boot를 사용하면 대부분 WebApplication을 개발할 것이다.
WebApplication을 개발 함에 있어 또한 대부분 MVC 패턴을 이용하여 개발을 진행한다.
또한 개발을 진행함에 있어 Test 코드의 작성은 선택이 아닌 필수이다.
Spring-boot는 Test를 작성함에있어 그렇게 어렵지 않으니 한번 알아보자.
자 다음과 같은 SampleContoller와 SampleService 가 있다.
@RestController
public class SampleController {
@Autowired
SampleService sampleService;
@GetMapping("hello")
public String helloName(){
return sampleService.getName()+"hello";
}
}
@Service
public class SampleService {
public String getName(){
return "jaeJoon";
}
}
SampleController는 "/hello"이라는 요청이 들어오면 SampleService의 getName()에서 jaeJoon을 받은 후
RestController 임으로 응답의 Body 부분에 jaeJoonhello 를 리턴해 줄 것이다.
이러한 흐름을 Test 코드를 통해 검증 하고 싶을 때 다음과 같이 진행하면 된다.
-
@SpringBootTest
-> 1-1) webApplication 통합 테스트를 진행한다.(default: 내장 톰캣을 사용하지 않고)
위와 같이 Mock up 된 웹 환경을 조작하기 위해선 MockMvc를 통한 조작을 해야 함
-> 1-2) Junit4 사용 시 @RunWith(SpringRunner.class) 와 함께 사용해야함( Junit5 사용시 적용하지 않아도 됨)
-
@AutoConfigureMockMvc
-> 위에서 말한 MockMvc를 주입받기 위한 애노테이션
자 이제 활용해보자.
@SpringBootTest
@AutoConfigureMockMvc
class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
void hello() throws Exception{
// 테스트코드 작성 !
}
}
이제 MockMvc의 Method를 알아보자.
크게 다음과 같이 3가지로 나눌 수 있다.
-
perform()
-> 어떠한 요청을 실행할 것인지 결정하는 Method (ex: get("url") , post("url") , put("url") 등등 )
-
andDo()
-> 요청을 실행하면서 할 행동
-
andExpect()
-> 요청의 기댓값 비교
대충 이렇게 설명할 수 있는데 3가지 Method를 체이닝 하여 이용한다.
이제 이용해 보면..
@Test
void hello() throws Exception{
mockMvc.perform(get("/hello"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("jaeJoonhello"));
}
}
다음과 같이 작성할 수 있는데..
perform 안에 있는 get()이라는 Method는 org.springframework.test.web.servlet.request.MockMvcRequestBuil ders에서
온다.
말 그대로 get 요청으로 /hello를 호출한다고 보면 된다.
또한 print() , status(). content 들은
org.springframework.test.web.servlet.result.MockMvcResultMatche rs에서 온 녀석들임으로 결과의 Response 값들을 출력하거나 확인할 수 있는 Method 들이라고 생각하자.
지금은 ApplicationContext 안에 들어 있는 Bean들을 그대로 이용하여 Test 코드를 작성했다.
하지만 때때로 ApplicationContext 안에 있는 Bean들을 그대로 이용해서 Test 코드를 작성하기에 힘든 경우가 발생할 수 있다.
그러한 경우 ApplicationContext 안에 있는 Bean을 Mock Up 하여 Test 코드 환경에서 필요한 Bean을 주입할 수 있다. 다음과 같이 작성하면 된다.
@MockBean
SampleService sampleService;
일단 Mock up 할 클래스를 @MockBean 애노테이션을 붙여 선언 후
@Test
void hello() throws Exception{
when(sampleService.getName()).thenReturn("mock Name"); // Test에서 사용할 getName() 의 리턴 값을 결정!
mockMvc.perform(get("/hello"))
.andExpect(status().isOk())
.andDo(print())
.andExpect(content().string("mock Namehello"));
}
다음과 같이 /hello라는 요청이 들어와서 SampleService 에있는 getName을 호출하게 되면 Test 코드에서 임시로 만든 Mock SampleService 주입하여 Test코드를 유연하게 짤 수 있다.
이러한 기능은 통합 테스트 환경이 아닌 단위 테스트 환경에서 더욱 큰힘을 발휘한다.
앞서 말한 통합테스트 환경이아닌 단위테스트 환경으로 변경하기 위해 선 @SpringBootTest
가 아닌 @WebMvcTest를
사용해보자.
@WebMvcTest(SampleController.class)
@AutoConfigureMockMvc
class MockSampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
void hello() throws Exception{
mockMvc.perform(get("/hello"))
.andExpect(status().isOk())
.andDo(print())
.andExpect(content().string("mock Namehello"));
}
}
다음과 같이 @WebMvcTest(SampleController.class)
즉 SampleController 만 테스트를 진행하고 싶을 때
이 상태로 실행하게 된다면 다음과 같은 오류를 만나보게 될 것이다.
SampleService의 Bean을 찾지 못하여 생기는 오류인데 당연히 통합 테스트가 아닌 단위 테스트 임으로 SampleService 빈은 등록되지 않는다.
이러한 경우 앞서 살펴보았던 MockBean을 이용하여 가짜 Bean을 등록하여 테스트를 진행할 수 있다.
@WebMvcTest(SampleController.class)
@AutoConfigureMockMvc
class MockSampleControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean
SampleService sampleService;
@Test
void hello() throws Exception{
when(sampleService.getName()).thenReturn("mock Name");
mockMvc.perform(get("/hello"))
.andExpect(status().isOk())
.andDo(print())
.andExpect(content().string("mock Namehello"));
}
}
앞서 말한 단위 테스트 말고도 spring boot는 더 많은 단위 테스트를 제공함으로 자세히 알고 싶다면 spring boot doc에서 test 부분을 살펴보자.
'Spring > boot' 카테고리의 다른 글
[Spring-boot] 웹MVC 2부 : 정적리소스 (0) | 2021.01.19 |
---|---|
[Spring-boot] 웹MVC (1부) : 소개 , ViewResolver (0) | 2021.01.19 |
[Spring-boot] Logging (0) | 2021.01.16 |
[Spring-boot] Profile 설정 (0) | 2021.01.15 |
[Spring-boot] 외부설정 2부 (0) | 2021.01.14 |