Spring Boot Controller Junit测试中ResponseEntity返回null问题排查
问题原因
- Controller代码大小写笔误(核心触发原因):
getData方法返回ResponseEntity时,传入的参数是大写的Records(类名),而非你之前接收服务返回值的小写records变量。如果你的Records类没有同名的静态实例变量,这里实际传入的就是null,直接导致body返回null。 - 参数匹配问题(潜在触发原因):如果
MyConsumerService接口中getGrpcResponse方法的入参类型不是String,或者实际调用参数和mock时声明的参数不匹配,Mockito会返回默认值null,也会导致body为空。 - 测试用例逻辑缺陷:即使修复上述问题,你当前的断言逻辑也会失败:mock返回时新建了一个
Records实例,断言时又新建了一个实例对比,默认equals方法判断的是对象内存地址,两个不同实例会被判定为不相等。 - (非报错原因,属于代码不规范)
MyConsumerServiceImpl中getGrpcResponse方法的入参data缺失类型声明,你业务能正常运行大概率是粘贴时的疏漏,建议检查补充为String data。
修复步骤
第一步:修复Controller笔误
把MyController中getData方法的返回语句修改为传入小写的records变量:
@GetMapping("/data") public ResponseEntity<Records> getData(@RequestParam("data") String data) { Records records = consumer.getGrpcResponse(data); // 将大写的类名Records改为小写的变量名records return new ResponseEntity<>(records, HttpStatus.OK); }
第二步:排查mock参数匹配问题
如果修复后依然返回null,可以先用泛化匹配验证是否是参数匹配问题:
// 用anyString()匹配任意字符串入参,验证mock是否能正常触发 when(mockerService.getGrpcResponse(anyString())).thenReturn(new Records());
如果修改后返回正常,说明getGrpcResponse方法的入参类型、入参值和mock声明的不一致,按需调整即可。
第三步:优化测试断言逻辑
两种方案二选一:
- 方案1:重写
Records类的equals和hashCode方法,按业务属性判断两个实例是否相等 - 方案2:测试中复用同一个
Records实例做mock返回和断言,修改测试代码如下:
@Test public void shouldGet(){ final var data="Hello"; // 提前创建实例,mock返回和断言都复用该对象 Records mockRecords = new Records(); when(mockerService.getGrpcResponse(data)).thenReturn(mockRecords); final var responseEntity=controller.getData(data); assertEquals(responseEntity.getBody(), mockRecords); }
内容的提问来源于stack exchange,提问作者stumbler
相关产品推荐
相关产品推荐

