Spring Boot 애플리케이션을 개발할 때, 컨트롤러 계층의 동작을 검증하기 위해 전체 애플리케이션을 실행하지 않고도 HTTP 요청을 시뮬레이션할 수 있는 방법이 필요하다. 이를 가능하게 하는 핵심 도구가 바로 MockMvc이다. 이 기능은 Spring Test 프레임워크에 포함되어 있으며, 서버를 실제로 구동하지 않아도 웹 레이어의 단위 테스트를 수행할 수 있도록 지원한다.
MockMvc란?
MockMvc는 Spring MVC의 요청 처리 흐름을 모의(mock)하여 컨트롤러 메서드를 직접 호출하고 그 결과를 검증하는 데 사용된다. 외부 네트워크나 서버 실행 없이 HTTP 요청과 응답을 시뮬레이션할 수 있어, 테스트 속도가 빠르고 반복성이 보장된다. 또한, 다양한 매처(matcher)와 결과 핸들러를 제공해 응답 상태, 콘텐츠 타입, JSON 구조 등을 쉽게 검증할 수 있다.
테스트 대상 컨트롤러 예제
다음은 학생 정보를 조회하고 파일을 업로드하는 기능을 제공하는 REST 컨트롤러이다.
package com.example.testapp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/students")
public class StudentApiController {
@Autowired
private StudentManagementService managementService;
@GetMapping("/list")
public ResponseEntity<List<Student>> retrieveAllStudents() {
List<Student> students = managementService.loadAll();
Student dummy = new Student();
dummy.setName("anonymous");
students.add(dummy);
return ResponseEntity.ok(students);
}
@PostMapping("/import")
public ResponseEntity<Void> importData(@RequestBody String payload) {
managementService.processImport(payload);
return ResponseEntity.accepted().build();
}
}
필요한 의존성 설정
MockMvc를 사용하려면 spring-boot-starter-test를 포함해야 한다. 이 스타터는 JUnit, Mockito, Spring Test, JsonPath 등을 통합 제공하며, 특히 @AutoConfigureMockMvc를 통해 자동으로 MockMvc 인스턴스를 구성할 수 있게 해준다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
주의할 점은, 만약 spring-boot-starter-security가 포함되어 있으면, 인증 없이는 엔드포인트 접근이 거부되어 테스트가 실패할 수 있으므로, 테스트 환경에서는 보안 설정을 비활성화하거나 별도의 테스트 프로필을 사용해야 한다.
컨트롤러 테스트 작성
다음은 위 컨트롤러를 테스트하는 JUnit 5 기반의 테스트 클래스이다. 서비스 계층은 Mockito를 사용해 목킹하고, MockMvc를 주입받아 요청을 시뮬레이션한다.
package com.example.testapp;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
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.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(StudentApiController.class)
class StudentApiControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private StudentManagementService managementService;
@Test
@DisplayName("모든 학생 목록 조회 성공")
void getAllStudents_Success() throws Exception {
mvc.perform(get("/api/students/list"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$[?(@.name == 'anonymous')]").exists())
.andDo(print());
verify(managementService, times(1)).loadAll();
}
@Test
@DisplayName("데이터 임포트 요청 처리 확인")
void importPayload_ValidatesExecution() throws Exception {
String testData = "{\"file\":\"data.csv\"}";
mvc.perform(post("/api/students/import")
.contentType(MediaType.APPLICATION_JSON)
.content(testData))
.andExpect(status().isAccepted())
.andDo(print());
verify(managementService, times(1)).processImport(testData);
}
}
주요 어노테이션 설명
- @WebMvcTest: 웹 계층에 집중한 테스트를 위한 어노테이션으로, 컨트롤러와 관련된 빈만 로드하여 테스트를 가볍게 만든다.
@SpringBootTest보다 더 효율적이다. - @MockBean: 애플리케이션 컨텍스트 내에 존재하는 빈을 Mockito 목으로 교체한다. 여기서는 실제 DB 접근 없이 서비스 호출 여부만 검증한다.
- @Autowired MockMvc:
@WebMvcTest와 함께 사용하면 자동으로 구성되며, HTTP 요청을 시뮬레이션할 수 있다.
MockMvc 요청 및 검증 흐름
각 테스트는 다음과 같은 흐름으로 진행된다:
mockMvc.perform()으로 HTTP 메서드와 경로 지정.contentType(),.content()등으로 요청 본문과 타입 설정.andExpect()으로 응답 상태, 콘텐츠, JSON 필드 등을 검증.andDo(print())로 콘솔에 전체 요청/응답 출력 (디버깅 용도)- 마지막으로 Mockito를 사용해 서비스 메서드 호출 횟수 검증