Spring Boot单元测试无论断言内容如何始终通过的问题排查
Spring Boot MockMvc测试在
mvn clean package中未触发断言失败的问题 问题描述
部署Spring Boot项目时,DevOps执行mvn clean package步骤,测试输出始终显示:
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
即使在第二个测试方法中故意使用接口实际不会返回的"fal"作为message的断言值,测试依然通过,未触发预期的失败。
测试代码
@SpringBootTest(classes = {DemoApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc public class MockMvcTestor { @Autowired private MockMvc mockMvc; @MockBean private FriendshipService friendshipService; @MockBean private UserService userService; @Test @DisplayName("测试 POST 创建好友关系接口") public void testFriendController_ValidUserId() throws Exception { // 模拟 userService 的行为 when(userService.getUser(1)).thenReturn(new User()); // 返回一个有效用户 when(userService.getUser(2)).thenReturn(new User()); // 返回一个有效用户 when(friendshipService.getFriendshipByTwoUserId(1, 2)).thenReturn(null); // 模拟没有好友关系 // 执行 POST 请求 mockMvc.perform(MockMvcRequestBuilders.post("/friendship/BuildRelations") .contentType(MediaType.APPLICATION_FORM_URLENCODED) .param("userId1", "1") .param("userId2", "2")) .andExpect(status().isOk()) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.jsonPath("$.code").value(0)) // 验证返回的 code .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Susad")) // 验证返回的 message .andReturn(); } @Test @DisplayName("测试 POST 创建用户接口") public void testAddUser_ValidUser() throws Exception { // 创建 UserDTO 对象 UserDTO userDTO = new UserDTO(); userDTO.setUsername("testuser"); userDTO.setPassword("password"); userDTO.setGender("Male"); userDTO.setEmail("test@example.com"); userDTO.setStatus("Active"); // 模拟 userService.addUser() 方法,不返回任何值 doNothing().when(userService).addUser(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any(byte[].class)); // 创建一个模拟的文件 MockMultipartFile avatarFile = new MockMultipartFile("avatorPic", "avatar.jpg", MediaType.IMAGE_JPEG_VALUE, "dummy data".getBytes()); // 发送 POST 请求 mockMvc.perform(MockMvcRequestBuilders.multipart("/users/addUser") .file(avatarFile) .param("username", userDTO.getUsername()) .param("password", userDTO.getPassword()) .param("gender", userDTO.getGender()) .param("email", userDTO.getEmail()) .param("status", userDTO.getStatus())) .andExpect(status().isOk()) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.jsonPath("$.code").value(0)) .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("fal")); } }
可能的原因及解决方法
1. Maven构建忽略了测试失败
DevOps工作流中的mvn命令可能添加了-Dmaven.test.failure.ignore=true参数,该参数会强制Maven忽略测试失败,继续执行构建,导致测试报告显示无失败。
- 排查:查看DevOps配置文件(如GitHub Actions YAML、Jenkinsfile)中的
mvn命令参数。 - 解决:移除该参数,让Maven在测试失败时终止构建。
2. JSONPath断言未正确匹配
如果控制器返回的JSON中不存在$.message字段,或字段类型与断言值不匹配,部分Spring版本可能不会触发断言失败。
- 排查:本地运行测试,通过
andDo(MockMvcResultHandlers.print())查看实际响应的JSON结构。 - 解决:添加字段存在性检查,完善断言:
.andExpect(MockMvcResultMatchers.jsonPath("$.message").exists()) .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("fal"))
3. MockBean配置导致控制器逻辑偏离预期
测试中Mock的Service返回空对象(如new User()),如果控制器需要对象的具体属性才能生成预期响应,会导致返回结果与断言不匹配,但由于Mock逻辑未覆盖控制器的分支判断,可能让断言看似"通过"。
- 解决:完善Mock对象的属性,确保符合控制器逻辑要求:
User user1 = new User(); user1.setId(1); when(userService.getUser(1)).thenReturn(user1);
4. 测试依赖版本不兼容
JUnit与Spring Test版本不兼容(如JUnit 4和JUnit 5混用),或Spring Boot版本与测试依赖不匹配,可能导致断言失效。
- 排查:检查
pom.xml中的spring-boot-starter-test依赖,确保版本与Spring Boot一致,避免同时引入JUnit 4和JUnit 5依赖。
内容的提问来源于stack exchange,提问作者姚 Haihan
相关产品推荐
相关产品推荐

