컨트롤러는 클라이언트의 요청을 받아 필요한 자원을 응답해주는 API이다.
우리가 컨트롤러 코드를 작성하고 나서 제대로 동작하는지 확인하기 위해서는 POSTMAN 과 같이 요청을 보내는 프로그램을 통해서 직접 요청을 보내고 , 응답이 잘 오는지 확인해봐야한다.
그런데 요청을 받기 위해서는 서버가 동작중 이어야 하므로 매번 서버를 띄우고 직접 주소로 요청을 보내는 방식으로 테스트를 하려니 너무 번거로웠다.
그래서 테스트 코드가 필요한것이다. 테스트 코드를 작성해두면 굳이 서버를 직접 띄우지 않고, 직접 요청을 하지 않더라도 내가 만든 API가 제대로 동작하는지 점검할 수 있다.
먼저 컨트롤러 API가 제대로 동작하는지 확인 할 수 있는 테스트 코드 짜는 방법을 알아보자.
그런데 서비스 클래스는 로직을 검사하는 방식으로 테스트 코드를 작성하면 되는데 컨트롤러의 API 경우 클라이언트의 요청을 제대로 전달 받는지 확인해야한다. 그렇다면 서버가 필수적이지 않을까? 어떻게 서버를 띄우지 않고도 테스트를 할 수 있다는 것일까?
그 이유는 MockMvc 라는 클래스 덕분이다.
MockMvc는 애플리케이션을 서버에 배포하지 않고도 테스트용 Mvc환경을 만들어 요청,전송,응답의 기능을 제공한다.
MockMvc 클래스를 사용하기 위해 @AutoConfigureMockMvc 어노테이션을 이용하여 자동으로 MockMvc 객체를 생성하고 구성할 수 있도록 한다.
@SpringBootTest // 테스트용 스프링 컨테이너 생성
@AutoConfigureMockMvc // MocMVC 생성 및 자동 구성
class BlogApiControllerTest {
@Autowired
protected MockMvc mockMvc;
@Autowired
protected ObjectMapper objectMapper; // 직렬화,역직렬화를 위한 클래스
@Autowired
private WebApplicationContext context;
@Autowired
private BlogRepository blogRepository;
@BeforeEach
public void mockMvcSetup(){
// mock 객체 설정
this.mockMvc= MockMvcBuilders.webAppContextSetup(context)
.build();
// 초기화
blogRepository.deleteAll();
}
@DisplayName("글 생성 api 테스트")
@Test
public void addArticle() throws Exception{
//given - 요청 설정
final String url = "/api/articles";
final String title = "제목";
final String content = "내용";
final AddArticleRequest request = new AddArticleRequest(title, content);
// 객체를 json으로 직렬화
final String requestBody = objectMapper.writeValueAsString(request);
// when 설정한 내용으로 요청 전송
ResultActions result = mockMvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(requestBody));
//then
result.andExpect(status().isCreated());
List<Article> articles = blogRepository.findAll();
assertThat(articles.size()).isEqualTo(1);
assertThat(articles.get(0).getTitle()).isEqualTo(title);
assertThat(articles.get(0).getContent()).isEqualTo(content);
}
}