
MockMVC는 Spring Framework에서 제공하는 테스트 도구로, 웹 애플리케이션의 MVC (Model-View-Controller) 구성 요소를 테스트하는 데 사용된다.
실제 서버를 실행하지 않고도 컨트롤러의 동작을 검증할 수 있기 때문에, 효율적이고 빠른 테스트가 가능하다.
MockMVC는 실제 HTTP 서버를 실행하지 않고도 요청을 보내고 응답을 받을 수 있게 해준다.
이는 테스트 속도를 높이고, 복잡성을 줄여준다.
HTTP GET, POST, PUT, DELETE와 같은 다양한 요청을 시뮬레이션할 수 있다.
이를 통해 컨트롤러가 올바르게 작동하는지 확인할 수 있다.
MockMVC를 사용하여 응답의 상태 코드, 콘텐츠 타입, 응답 본문 등을 검증할 수 있다.
이를 통해 예상한 결과와 실제 결과를 비교할 수 있다.
Spring의 DI(Dependency Injection)와 AOP(Aspect-Oriented Programming)와 잘 통합되어, 복잡한 설정 없이도 쉽게 테스트할 수 있다.
package org.mockmvc.mockmvctest.service;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
public List<String> getAllUsers() {
return List.of("User1", "User2", "User3");
}
}
package org.mockmvc.mockmvctest.controller;
import org.mockmvc.mockmvctest.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/users")
public List<String> getUsers() {
return userService.getAllUsers();
}
}
package org.mockmvc.mockmvctest.controller;
import org.junit.jupiter.api.Test;
import org.mockmvc.mockmvctest.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import java.util.List;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean // UserService를 모킹
private UserService userService;
@Test
public void testGetUsers() throws Exception {
// UserService의 getAllUsers() 메서드가 호출될 때 반환할 값을 설정합니다.
given(userService.getAllUsers()).willReturn(List.of("User1", "User2", "User3"));
// MockMvc를 사용하여 GET 요청을 수행하고, 응답을 검증합니다.
mockMvc.perform(get("/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0]").value("User1"))
.andExpect(jsonPath("$[1]").value("User2"))
.andExpect(jsonPath("$[2]").value("User3"));
}
}

테스트가 잘 통과한 것을 확인할 수 있다.

package org.mockmvc.mockmvctest.controller;
import org.junit.jupiter.api.Test;
import org.mockmvc.mockmvctest.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import java.util.List;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean // UserService를 모킹
private UserService userService;
@Test
public void testGetUsers() throws Exception {
// UserService의 getAllUsers() 메서드가 호출될 때 반환할 값을 설정합니다.
given(userService.getAllUsers()).willReturn(List.of("User1", "User2", "User3"));
// MockMvc를 사용하여 GET 요청을 수행하고, 응답을 검증합니다.
mockMvc.perform(get("/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0]").value("UNKNOWN")) // 테스트 실패 확인을 위해 변경
.andExpect(jsonPath("$[1]").value("User2"))
.andExpect(jsonPath("$[2]").value("User3"));
}
}
테스트 실패를 확인하기 위해 perform() 메서드 체이닝 중 andExpect() 를 User1 에서 UNKNOWN 으로 변경해보았다.
이미지를 보면 알 수 있듯이, 예상되는 결과와 실제 결과가 다르기에 테스트 실패를 알려준다.
given(userService.getAllUsers()).willReturn(List.of("User1", "User2", "User3"));
userService.getAllUsers()메서드를 호출하면List.of("User1", "User2", "User3")를 반환받도록 명시해주었는데 TEST코드에서 왜 반환되는 결과를 다시 적어주는가?
@MockBean 어노테이션을 사용하여 UserService의 Mock 객체를 생성하면, 해당 Mock 객체는 실제 서비스 클래스의 구현과는 별개로 동작한다.
즉, Mock 객체는 실제 구현을 대체하여, 특정 동작을 정의하고 이를 테스트에 사용할 수 있게 해준다.
만약 내가 given(userService.getAllUsers()).willReturn(List.of("User4", "User5")); 처럼 서비스 반환 값과 다르게 하더라도 정상적으로 작동한다.
* 다만, 반환 타입은 동일하게 해줘야 한다.