JUnit Mockito测试报错:JSON路径$.title无值(状态码200正常)
Spring Boot Controller测试:updateProduct接口JSON断言失败问题
问题现象
测试updateProduct接口时,状态码返回200正常,但断言JSON路径$.title抛出错误:
java.lang.AssertionError: No value at JSON path "$.title"
查看响应详情,发现响应体为空,Content-Type为null。
初始化代码
@Autowired private MockMvc mockMvc; @MockBean private ProductServiceImp productServiceImp; @Autowired private ObjectMapper objectMapper;
测试方法
@Test @Order(3) public void updateProductController_ShouldReturnOk() throws Exception { // Arrange when(productServiceImp.updateProduct(product, 1L)).thenReturn(product); // Act ResultActions response = mockMvc.perform(put("/api/products/{id}", 1L) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(product)) ); // Assert response.andExpectAll( status().isOk(), jsonPath("$.title", CoreMatchers.is(product.getTitle())) ); }
控制器代码
// 类上标注了@RequestMapping(value = "api/products") @PutMapping("/{id}") public ResponseEntity<Product> updateProduct(@PathVariable Long id, @RequestBody Product product) { Product updatedProduct = productService.updateProduct(product, id); return ResponseEntity.ok(updatedProduct); }
请求与响应详情
请求详情
MockHttpServletRequest: HTTP Method = PUT Request URI = /api/products/1 Parameters = {} Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"246"] Body = {"id":1,"title":"Fake Product","price":99999999,"rating":{"rate":5.0,"count":1},"category":"Fake Category","description":"Fake description","image":"FakeImage.jpg"} Session Attrs = {}
响应详情
MockHttpServletResponse: Status = 200 Error message = null Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"] Content type = null Body = Forwarded URL = null Redirected URL = null Cookies = []
解决方案
1. 修正Mockito参数匹配逻辑
默认Mockito使用引用匹配,如果测试中传入的product对象和控制器接收的不是同一个实例,Mock的Service不会返回预设值,导致控制器返回空。改用参数匹配器:
// 替换原Arrange代码 when(productServiceImp.updateProduct(any(Product.class), eq(1L))).thenReturn(product);
需引入Mockito静态方法:
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq;
2. 检查Product类的序列化配置
确保Product类满足Jackson序列化要求:
- 有无参构造器:
public Product() {} - 所有需要序列化的属性都有对应的getter方法(比如
getTitle())。
3. 修正Service注入匹配问题
控制器中注入的是productService(接口),但测试中Mock的是实现类ProductServiceImp,导致注入不匹配,控制器实际调用的不是Mock的Service。将测试中的MockBean改为接口类型:
@MockBean private ProductService productService; // 替换原ProductServiceImp
同时调整Mockito语句:
when(productService.updateProduct(any(Product.class), eq(1L))).thenReturn(product);
4. 调试响应内容
在测试中添加响应打印,方便排查细节:
response.andDo(print()) // 在andExpectAll之前添加 .andExpectAll( status().isOk(), jsonPath("$.title", CoreMatchers.is(product.getTitle())) );
内容的提问来源于stack exchange,提问作者モブ Mobu
相关产品推荐
相关产品推荐

