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

Mock单元测试异常:预期返回‘Success.’却得到空ResponseEntity求助

排查控制器单元测试返回空响应的问题

根据你描述的情况,明明Mock了gameService.addGame()返回"Success.",但测试中得到空响应,结合代码细节来看,最可能的原因是Mockito的参数匹配未生效,导致gameService.addGame()实际返回了null,最终Spring MVC将ResponseEntity.ok(null)序列化为空响应体。下面具体分析并给出解决办法:

核心原因:GameDTO的对象匹配失败

在你的测试代码中,你创建了一个GameDTO实例并传入when(gameService.addGame(gameDTO)).thenReturn("Success."),但控制器通过@RequestBody接收的是Spring MVC从JSON解析出来的全新GameDTO对象。如果GameDTO类没有重写equals()和hashCode()方法,Mockito会用默认的对象引用相等来匹配参数——这两个对象不是同一个引用,所以Mock的返回值不会生效,gameService.addGame()会返回默认的null,最终导致响应体为空。

另外你提到Postman调用正常,这是因为实际运行时gameService.addGame()会真实执行并返回"Success.",和Mock的逻辑无关,所以接口表现正常。

解决方案

方案1:重写GameDTO的equals()和hashCode()方法

让Mockito可以通过对象的属性值来匹配参数,而不是依赖引用相等。例如:

public class GameDTO {
    private Long user1Id;
    private Long user2Id;
    private String result;

    // 构造函数、getter、setter

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        GameDTO gameDTO = (GameDTO) o;
        return Objects.equals(user1Id, gameDTO.user1Id) &&
               Objects.equals(user2Id, gameDTO.user2Id) &&
               Objects.equals(result, gameDTO.result);
    }

    @Override
    public int hashCode() {
        return Objects.hash(user1Id, user2Id, result);
    }
}

方案2:使用Mockito的参数匹配器

如果你不想修改GameDTO类,可以改用any(GameDTO.class)来匹配任意GameDTO对象,这样Mock的返回值就会生效:

// 替换原来的when语句
when(gameService.addGame(any(GameDTO.class))).thenReturn("Success.");

额外验证点

为了确认这个问题,你可以在测试中临时添加一行代码,验证gameService.addGame()的调用情况:

// 在andReturn()之后添加
verify(gameService).addGame(any(GameDTO.class));

如果运行测试时抛出Wanted but not invoked的异常,就说明参数匹配确实失败了,进一步验证了我们的结论。


内容的提问来源于stack exchange,提问作者devo9191

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 21:07:39