You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 19:17:13