- 스프링 프레임워크에서 제공하는 웹 애플리케이션 테스트용 라이브러를 의미한다. 이를 사용하면 웹 애플리케이션의 다양한 컴포넌트를 테스트할 수 있다.
- MockMvc를 사용하면 HTTP 요청을 작성하고 컨트롤러의 응답을 검증할 수 있습니다. 이를 통해 통합 테스트를 실행하지 않고도 컨트롤러의 동작을 확인할 수 있습니다.
- 쉽게 설명해서 내가 컨트롤러 테스트를 하고싶을 때 실제 서버에 구현한 애플리케이션을 올리지 않고(실제 서블릿 컨테이너를 사용하지 않고) 테스트용으로 시뮬레이션하여 MVC가 되도록 도와주는 클래스이다!
- MockMvc를 이용하여 컨트롤러의 동작을 테스트하는 데 사용됩니다.
- 컨트롤러의 엔드포인트를 호출하여 HTTP 클라이언트의 요청을 모방하고 적절한 응답을 확인하기 위해 테스트를 수행합니다.
- 이러한 테스트 과정을 통해 애플리케이션의 서비스 로직이나 API 엔드포인트가 의도한 대로 동작하는지 확인하고, 버그를 발견하고 수정하는 데 도움을 주는 것입니다.
- TestCase → MockMvc
- TestCase 내에서 MockMvc 객체를 생성합니다. 이 객체는 테스트할 컨트롤러와 상호작용을 하는 데 사용이 됩니다.
- MockMvc → TestDispatcher Servlet
- MockMvc를 사용하여 원하는 엔드포인트에 요청을 보냅니다. 또한 해당 요청에 필요한 파라미터, 헤더 또는 쿠키 등을 설정합니다.
- 예를 들어, GET 요청을 보내고 싶다면 perform(MockMvcRequestBuilders.get("/endpoint"))와 같이 요청을 설정합니다.
- 파라미터 설정은 param("paramName", "paramValue")와 같이 파라미터를 설정할 수 있습니다.
- TestDispatcher Servlet → Controller
- 요청을 실행하고 응답을 받습니다. andExpect 메서드를 사용하여 응답의 상태코드, 헤더, 본문 등을 검증할 수 있습니다.
- MockMvc → TestCase
- 필요한 검증을 추가합니다.
- 예를 들어, 응답 본문의 내용을 검증하고 싶다면 andExpect(content(). string("expectedValue"))와 같이 검증을 추가합니다.
메서드 설명 perform()MockMvc를 사용하여 HTTP 요청을 실행합니다. andExpect()컨트롤러의 응답을 검증합니다. andExpect(status().isOk())응답 상태 코드가 200인지 확인합니다. andExpect(content().string("expected"))응답 본문의 내용이 "expected"인지 확인합니다.andExpect(jsonPath("$.property").value("expected"))JSON 응답에서 특정 속성의 값이 "expected"인지 확인합니다.andExpect(view().name("expectedView"))응답에 대한 뷰의 이름이 "expectedView"인지 확인합니다.andExpect(model().attribute("attributeName", "expectedValue"))모델 속성의 값이 "expectedValue"인지 확인합니다.andExpect(redirectedUrl("expectedUrl"))리다이렉트된 URL이 "expectedUrl"인지 확인합니다.
- MockMvc 메서드를 이용한 사용예시
@ExtendWith(MockitoExtension.class) // Junit5 - Mockito 연동 class CodeControllerTest { private MockMvc mockMvc; // HTTP 호출을 위한 MockMVC 사용 @BeforeEach void setUp() { mockMvc = MockMvcBuilders.standaloneSetup(codeController).build(); } @Test public void testExample() throws Exception { mockMvc.perform(get("/example")) // "/example"로 GET 요청 수행 .andExpect(status().isOk()) // 상태 코드 200인 성공적인 응답을 기대합니다 .andExpect(content().string("expected")) // 응답 내용이 "expected"와 같을 것으로 기대합니다 .andExpect(jsonPath("$.property").value("expected")) // JSON 속성 "property"의 값이 "expected"와 같을 것으로 기대합니다 .andExpect(view().name("expectedView")) // 뷰 이름이 "expectedView"와 같을 것으로 기대합니다 .andExpect(model().attribute("attributeName", "expectedValue")) // 모델 속성 "attributeName"의 값이 "expectedValue"와 같을 것으로 기대합니다 .andExpect(redirectedUrl("expectedUrl")); // "expectedUrl"로의 리다이렉트를 기대합니다 } }
- MockMvc를 사용하여 실행한 ‘HTTP 요청에 대한 결과’를 나타냅니다. 이를 통해 컨트롤러의 응답을 검증하고 원하는 동작을 수행할 수 있습니다.
메서드 설명 andReturn()해결된 MvcResult객체를 반환합니다.andReturn(MvcResult)반환할 MvcResult를 설정합니다.andDo(ResultHandler)결과에 대해 추가 작업을 수행합니다. andDo(ResultMatcher)결과에 ResultMatcher를 추가합니다.andExpect(ResultMatcher)결과에 대한 기대치로 ResultMatcher를 추가합니다.
ResultActions 메서드 사용 예시
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; public class SampleTest { private MockMvc mockMvc; // ... public void sampleTest() throws Exception { ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/sample")); resultActions .andExpect(status().isOk()) .andExpect(jsonPath("$.message").value("Hello, World!")); // Add more assertions or actions as needed } }
| 어노테이션 | 설명 |
|---|---|
@ExtendWith(MockitoExtension.class) | Mockito를 사용하여 모킹하기 위해 테스트 클래스에 적용됩니다. |
@WebMvcTest | 웹 MVC 테스트를 위해 스프링 컨텍스트를 구성합니다. |
@AutoConfigureJsonTesters | JSON 테스트를 위해 JsonTester의 자동 구성을 활성화합니다. |
@AutoConfigureMockMvc | MockMvc를 자동으로 구성하는 데 사용됩니다. |
@Mock | 모킹 대상 객체를 생성하여 주입합니다. |
@MockBean | Spring 컨텍스트에서 Mock 객체를 생성하여 주입합니다. |
@SpringBootTest | 스프링 부트 애플리케이션의 통합 테스트를 위해 스프링 컨텍스트를 구성합니다. |
@BeforeEach | 각각의 테스트 메서드가 실행되기 전에 실행되는 메서드를 지정합니다. |
@Test | 테스트 메서드를 지정합니다. |
컨트롤러를 테스트한다고 가정하자!
@Test @BlogMockUser @DisplayName("글 작성 요청시 title값은 필수다.") void test2() throws Exception { // given PostCreate request = PostCreate.builder() .content("내용입니다.") .build(); String json = objectMapper.writeValueAsString(request); // mockMvc에게 컨트롤러에 대한 정보를 입력하자. // expected mockMvc.perform(post("/api/posts") // 해당 url로 요청 .contentType(APPLICATION_JSON) // Json 타입으로 지정 .content(json)) // json으로 내용 등록 .andExpect(status().isBadRequest())// 응답 status를 isBadRequest로 테스트 .andExpect(jsonPath("$.code").value("400")) .andExpect(jsonPath("$.message").value("잘못된 요청입니다.")) .andExpect(jsonPath("$.validation.title").value("타이틀을 입력하세요.")) .andDo(print()); // 응답값 print }
- MockMvc를 생성한다.
- MockMvc에게 요청에 대한 정보를 입력한다.
- 요청에 대한 응답값을 Expect를 이용하여 테스트한다.
- Expect가 모두 통과하면 테스트 통과
- Expect가 1개라도 실패하면 테스트 실패