本文目录导读:

我来详细介绍Spring Boot中使用MockMvc进行控制器测试的方法。
基础环境配置
Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
示例控制器
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
return ResponseEntity.ok(user);
}
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User created = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
return ResponseEntity.ok(userService.findAll());
}
}
测试方式一:@WebMvcTest(推荐)
基础测试类
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void testGetUser_Success() throws Exception {
// 准备测试数据
User mockUser = new User(1L, "张三", "zhangsan@example.com");
when(userService.findById(1L)).thenReturn(mockUser);
// 执行请求并验证
mockMvc.perform(get("/api/users/1")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("张三"))
.andExpect(jsonPath("$.email").value("zhangsan@example.com"));
}
}
完整测试示例
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Autowired
private ObjectMapper objectMapper;
// 测试获取用户信息
@Test
void testGetUser_Success() throws Exception {
User mockUser = new User(1L, "张三", "zhangsan@example.com");
when(userService.findById(1L)).thenReturn(mockUser);
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id").value(1))
.andExpect(jsonPath("$.name").value("张三"));
}
// 测试用户不存在
@Test
void testGetUser_NotFound() throws Exception {
when(userService.findById(99L)).thenThrow(new UserNotFoundException("用户不存在"));
mockMvc.perform(get("/api/users/99"))
.andExpect(status().isNotFound());
}
// 测试创建用户
@Test
void testCreateUser_Success() throws Exception {
User user = new User(null, "李四", "lisi@example.com");
User savedUser = new User(2L, "李四", "lisi@example.com");
when(userService.save(any(User.class))).thenReturn(savedUser);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(user)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.id").value(2))
.andExpect(jsonPath("$.name").value("李四"));
}
// 测试参数验证失败
@Test
void testCreateUser_ValidationFailed() throws Exception {
User invalidUser = new User(null, "", "invalid-email");
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(invalidUser)))
.andExpect(status().isBadRequest());
}
}
测试方式二:@SpringBootTest
集成测试
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private UserRepository userRepository;
@BeforeEach
void setUp() {
userRepository.deleteAll();
}
@Test
void testFullFlow() throws Exception {
// 创建用户
String userJson = "{\"name\":\"王五\",\"email\":\"wangwu@example.com\"}";
MvcResult result = mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().isCreated())
.andReturn();
String responseBody = result.getResponse().getContentAsString();
User createdUser = objectMapper.readValue(responseBody, User.class);
// 查询用户
mockMvc.perform(get("/api/users/" + createdUser.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("王五"));
}
}
测试工具方法封装
通用测试工具类
@Component
public class TestUtils {
public static ResultActions performGet(MockMvc mockMvc, String url) throws Exception {
return mockMvc.perform(get(url)
.accept(MediaType.APPLICATION_JSON));
}
public static ResultActions performPost(MockMvc mockMvc, String url, Object body) throws Exception {
ObjectMapper mapper = new ObjectMapper();
return mockMvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsString(body)));
}
public static <T> T parseResponse(MvcResult result, Class<T> clazz) throws Exception {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(result.getResponse().getContentAsString(), clazz);
}
}
常用断言技巧
多种断言示例
class AdvancedAssertionsTest {
@Test
void testAdvancedAssertions() throws Exception {
// JSON路径断言
mockMvc.perform(get("/api/users"))
.andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$[0].name").value("张三"))
.andExpect(jsonPath("$[0].age", greaterThan(18)))
.andExpect(jsonPath("$[*].name", hasItem("李四")))
.andExpect(jsonPath("$[?(@.name == '王五')]").exists());
// 响应头断言
mockMvc.perform(get("/api/users"))
.andExpect(header().string("Content-Type", containsString("application/json")))
.andExpect(header().exists("X-Request-ID"));
// Cookie断言
mockMvc.perform(get("/api/users")
.cookie(new Cookie("session-id", "abc123")))
.andExpect(cookie().exists("session-id"));
// 请求参数断言
mockMvc.perform(get("/api/users")
.param("page", "1")
.param("size", "10"))
.andExpect(status().isOk());
}
}
模拟安全认证
带安全认证的测试
@WebMvcTest(UserController.class)
class SecurityTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
@WithMockUser(username = "admin", roles = {"ADMIN"})
void testAdminEndpoint() throws Exception {
mockMvc.perform(get("/api/admin/users"))
.andExpect(status().isOk());
}
@Test
@WithAnonymousUser
void testUnauthorized() throws Exception {
mockMvc.perform(get("/api/admin/users"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(username = "user", roles = {"USER"})
void testForbidden() throws Exception {
mockMvc.perform(get("/api/admin/users"))
.andExpect(status().isForbidden());
}
}
文件上传测试
文件上传示例
class FileUploadTest {
@Test
void testFileUpload() throws Exception {
MockMultipartFile file = new MockMultipartFile(
"file",
"test.txt",
"text/plain",
"Hello, World!".getBytes()
);
mockMvc.perform(multipart("/api/upload")
.file(file)
.param("description", "测试文件"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.fileName").value("test.txt"));
}
}
最佳实践建议
测试结构组织
class UserControllerTest {
// 使用Nested组织测试
@Nested
class GetUserTests {
@Test
void shouldReturnUserWhenExists() {}
@Test
void shouldReturn404WhenNotExists() {}
}
@Nested
class CreateUserTests {
@Test
void shouldCreateUserWithValidData() {}
@Test
void shouldReturn400WithInvalidData() {}
}
}
这些示例涵盖了Spring Boot中使用MockMvc测试控制器的常见场景,你可以根据实际需求选择合适的测试方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播