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
相关产品推荐
相关产品推荐

