Web API를 작성하고 테스트를 수행하기 위해서 스프링 부트 애플리케이션을 실행하고 Restlet이나 Swagger등을 이용해 개발자가 직접 테스트를 수행
-> Web API를 실행하는 시간보다 웹 어플리케이션을 실행하고 종료하는 시간이 더 오래걸리는 상황 발생
GuestbookApiController에서는 GuestbookService라는 서비스 객체를 가져와 사용하지만, 테스트할 경우 Mock 객체를 생성해 사용하도록 함
package kr.or.connect.guestbook.controller;
import kr.or.connect.guestbook.config.ApplicationConfig;
import kr.or.connect.guestbook.config.WebMvcContextConfiguration;
import kr.or.connect.guestbook.dto.Guestbook;
import kr.or.connect.guestbook.service.GuestbookService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {WebMvcContextConfiguration.class, ApplicationConfig.class })
public class GuestbookApiControllerTest {
// Mockito 프레임워크에 위해 생성된 Mock 객체를 사용할 수 있음
@InjectMocks
public GuestbookApiController guestbookApiController;
//GuestbookApiControllerTest에서 사용되는 객체의 Mock 객체 생성
@Mock
GuestbookService guestbookService;
//guestbookApiController를 테스트 하기 위한 MockMvc객체를 생성
private MockMvc mockMvc;
// 테스트 메소드 실행 전 @Before 어노테이션 붙은 메소드 실행
@Before
public void createController() {
// @Mock이 붙은 객체 초기화
MockitoAnnotations.initMocks(this);
// MockMVC타입의 변수 mockMvc를 초기화
mockMvc = MockMvcBuilders.standaloneSetup(guestbookApiController).build();
}
@Test //테스트 메소드
public void getGuestbooks() throws Exception {
Guestbook guestbook1 = new Guestbook();
guestbook1.setId(1L);
guestbook1.setRegdate(new Date());
guestbook1.setContent("hello");
guestbook1.setName("kim");
List<Guestbook> list = Arrays.asList(guestbook1);
//when(목객체.목객체메소드호출()).threnReturn(목객체 메소드가 리턴 할 값)
//guestbookService.getGuestbooks(0) 이 호출되면 위에서 선언된 list객체가 리턴 되도록 함
when(guestbookService.getGuestbooks(0)).thenReturn(list);
// MockMvcRequestBuilders를 이용해 MockMvc에 호출할 URL생성
//application/json형식으로 /guestbooks를 GET방식으로 호출한다는 의미
RequestBuilder reqBuilder = MockMvcRequestBuilders.get("/guestbooks").contentType(MediaType.APPLICATION_JSON);
//mockMvc.perform(reqBuilder) 는 reqBuilder에 해당하는 URL에 대한 요청을 보냈다는 것을 의미
// 상태코드값이 200이 나오면 처리 내용을 출력
mockMvc.perform(reqBuilder).andExpect(status().isOk()).andDo(print());
//Json 결과에 “name”:”kim”이 있을 경우에만 성공
//mockMvc.perform(reqBuilder).andExpect(jsonPath("$.list[0].name").value("kim"));
//Mock 객체의 getGuestbooks(0)메소드가 호출됐다면 검증 성공
verify(guestbookService).getGuestbooks(0);
}
@Test
public void deleteGuestbook() throws Exception {
Long id = 1L;
when(guestbookService.deleteGuestbook(id, "127.0.0.1")).thenReturn(1);
// “/guestbooks/” + id 경로를 DELETE방식으로 호출하기 위한 경로 정보를 저장
RequestBuilder reqBuilder = MockMvcRequestBuilders.delete("/guestbooks/" + id).contentType(MediaType.APPLICATION_JSON);
//reqBuilder에 해당하는 URL호출 후 상태코드가 200일때 실행 결과 출력
mockMvc.perform(reqBuilder).andExpect(status().isOk()).andDo(print());
//guestbookService 목객체의 deleteGuestbook(id, “127.0.0.1”)메소드가 Web API가 동작하면서 호출되었다면 성공
verify(guestbookService).deleteGuestbook(id, "127.0.0.1");
}
}