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

REST-API @PutMapping控制器单元测试JSON路径无值报错排查

问题根因

报错核心是Mockito存根逻辑写错,具体有两个问题:

  • UpdateEmployee方法mock返回值错误:方法参数索引从0开始计数,UpdateEmployee(Long employeeId, Employee employee)的第0位参数是Long类型的员工ID1L,第1位才是传入的Employee对象。现有代码willAnswer里返回invocationOnMock.getArgument(0),实际返回的是数字1,接口响应体里塞的是Long类型数值,不是Employee结构的JSON对象,自然找不到$.firstName对应的路径。
  • 存在冗余无效mock:你写的BDDMockito.given(employeeService.getEmployeeById(employeeId))存根完全没用——控制器方法里根本没调用getEmployeeById,这个查询逻辑是UpdateEmployee服务方法的内部实现,控制器单元测试里服务层是完全mock的,不会走内部逻辑,这段代码属于多余内容。
修复方案
  • 修正UpdateEmployee的mock返回逻辑:推荐直接用willReturn返回构造好的更新后员工对象,写法更简单不易错;如果要保留willAnswer写法,记得取索引为1的参数。
  • 删除多余的getEmployeeByIdmock语句。

修复后的given段代码示例:

//given
Long employeeId = 1L;

Employee employeeInfo = Employee.builder()
        .firstName(NEW_TEST_FIRST_NAME)
        .lastName(NEW_TEST_LAST_NAME)
        .email(NEW_TEST_EMAIL)
        .build();

// 只需要mock控制器实际调用的服务方法即可
BDDMockito.given(employeeService.UpdateEmployee(employeeId, employeeInfo))
        .willReturn(employeeInfo);

如果用willAnswer写法,对应代码改成:

BDDMockito.given(employeeService.UpdateEmployee(employeeId, employeeInfo))
        .willAnswer(invocationOnMock -> invocationOnMock.getArgument(1));

改完后接口会正确返回Employee结构的JSON,断言即可正常通过。

补充:控制器层单元测试只需要验证路由匹配、参数解析、响应状态码、响应封装逻辑是否正确,不需要关心服务方法内部的实现细节(比如服务里调用的repository查询、保存逻辑,是服务层单元测试要覆盖的内容,不需要在控制器测试里mock)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:09:18