Spring MockMvc与WebMvcTest测试未返回预期结果问题排查
Spring Boot MockMvc测试返回404问题排查与解决
开发Spring Boot应用时,编写TableController的MockMvc测试,调用getById方法时始终返回404,无法获取模拟的Table数据。
测试配置代码
@WebMvcTest(TableController.class) @WithMockUser public class TableControllerTests { @Autowired private MockMvc mockMvc; @MockBean private TableService tableService; private String rootUri; @BeforeEach public void setUp(){ this.rootUri = "/tables"; } }
测试方法代码
@Test public void getTableById() throws Exception { // Arrange Integer id = 1; Table table = new Table(id); String tableUri = rootUri + "/" + id; // /tables/1 when(this.tableService.getById(id)).thenReturn(table); // Act RequestBuilder request = MockMvcRequestBuilders.get(tableUri, id) .accept(MediaType.APPLICATION_JSON); // Assert this.mockMvc.perform(request) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.id", is(id))); }
控制器代码
@RestController @RequestMapping("/tables") public class TableController { @Autowired TableService tableService; @GetMapping("/{id}") public ResponseEntity<Table> getById(@PathVariable Integer id){ Table table = this.tableService.getById(id); if (table != null) { return ResponseEntity.ok(table); // 200 OK } else { return ResponseEntity.notFound().build(); // 404 Not Found } } }
可能的原因及解决方案
1. JUnit注解不匹配导致初始化失败
如果测试类使用JUnit 4但误用了JUnit 5的@BeforeEach注解,setUp方法不会执行,rootUri保持为null,最终请求路径变成/null/1,触发404。
解决方法:
- 若用JUnit 5,确保导入
org.junit.jupiter.api.BeforeEach和org.junit.jupiter.api.Test; - 若用JUnit 4,将
@BeforeEach替换为org.junit.Before,@Test替换为org.junit.Test。
2. 请求路径构建冗余参数
测试中MockMvcRequestBuilders.get(tableUri, id)的第二个参数是冗余的:tableUri已拼接id,无需再传递id作为URI模板参数,虽不会直接引发404,但易混淆。
解决方法:
修改请求构建代码,去掉冗余参数:
RequestBuilder request = MockMvcRequestBuilders.get(tableUri) .accept(MediaType.APPLICATION_JSON);
或使用URI模板方式,更清晰规范:
RequestBuilder request = MockMvcRequestBuilders.get("/tables/{id}", id) .accept(MediaType.APPLICATION_JSON);
3. MockBean未正确生效
若TableService的MockBean未注入控制器,控制器会调用真实服务(若存在),返回null触发404。
验证与解决:
在断言部分添加Mock调用验证,确认服务方法被触发:
this.mockMvc.perform(request) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.id", is(id))) .andDo(result -> verify(tableService).getById(id));
若验证抛出NoInteractionsWanted,说明请求未达控制器,需检查路径配置;若验证通过,则Mock已生效,排查其他问题。
4. Table类序列化问题(影响后续断言)
若Table类无getId()等getter方法,Spring无法序列化对象为JSON,虽不会导致404,但会使jsonPath断言失败。
解决方法:
为Table类添加对应getter方法:
public class Table { private Integer id; public Table(Integer id) { this.id = id; } public Integer getId() { return id; } }
内容的提问来源于stack exchange,提问作者Tomás Iglesias
相关产品推荐
相关产品推荐

