JUnit测试Post接口报错:JSON路径$.id无值问题排查
排查JUnit测试中JSON路径$.id无值的问题
问题背景
编写Post方法控制器的JUnit测试时,出现错误:java.lang.AssertionError: No value at JSON path "$.id",附带完整错误栈信息,以下是相关代码片段及错误详情。
测试代码
@Test public void testCreateCar() throws Exception { String custJson = "{\"name\": \"John Doe\", " + "\"street\": \"123 Main St\", " + "\"house_No\": \"45B\", " + "\"place\": \"Springfield\", " + "\"email\": \"john.doe@example.com\", " + "\"ph_Number\": \"1234567890\"}"; CustomerEntity customer = new CustomerEntity(); customer.setters except ID... CustomerEntity customer2 = new CustomerEntity(); customer2.setters..... given(custService.createCust(customer)).willReturn(customer2); mvc.perform(MockMvcRequestBuilders.post("/api/createCust") .contentType(MediaType.APPLICATION_JSON).content(custJson)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1)) .andExpect(MockMvcResultMatchers.jsonPath("$.name").value("John Doe")) .andExpect(MockMvcResultMatchers.jsonPath("$.street").value("123 Main St")) .andExpect(MockMvcResultMatchers.jsonPath("$.house_No").value("45B")) .andExpect(MockMvcResultMatchers.jsonPath("$.place").value("Springfield")) .andExpect(MockMvcResultMatchers.jsonPath("$.email").value("john.doe@example.com")) .andExpect(MockMvcResultMatchers.jsonPath("$.ph_Number").value("1234567890")); }
CustomerEntity实体类
@Entity public class CustomerEntity { public CustomerEntity(Integer id, String name, String street, String house_No, String place, @Email String email, @Pattern(regexp = "(^$|[0-9]{10})") String ph_Number) { super(); this.id = id; this.name = name; this.street = street; this.house_No = house_No; this.place = place; this.email = email; this.ph_Number = ph_Number; } //constructor public CustomerEntity() {} @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; private String name; private String street; private String house_No; private String place; @Email private String email; @Pattern(regexp = "(^$|[0-9]{10})") private String ph_Number; }
Controller端点
@PostMapping("/createCust") public ResponseEntity<CustomerEntity> createCust(@Valid @RequestBody CustomerEntity cust) { CustomerEntity customer = custService.createCust(cust); return ResponseEntity.status(HttpStatus.OK).body(customer); }
Service代码
public CustomerEntity createCust(CustomerEntity cust) { return custRepo.save(cust); }
错误信息
java.lang.AssertionError: No value at JSON path "$.id" at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:302) at org.springframework.test.util.JsonPathExpectationsHelper.assertValue(JsonPathExpectationsHelper.java:99) at org.springframework.test.web.servlet.result.JsonPathResultMatchers.lambda$value$2(JsonPathResultMatchers.java:111) at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:214) at com.rupesh.assesment.carlease.controller.CustomerControllerTest.testCreateCar(CustomerControllerTest.java:57) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) Caused by: java.lang.IllegalArgumentException: json can not be null or empty at com.jayway.jsonpath.internal.Utils.notEmpty(Utils.java:401) at com.jayway.jsonpath.JsonPath.read(JsonPath.java:390) at com.jayway.jsonpath.JsonPath.read(JsonPath.java:377) at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:299) ... 7 more
排查与修复方案
1. Mock参数匹配问题
测试中手动构造的customer对象,和MockMvc将custJson转换后的CustomerEntity对象大概率不是同一个实例(默认equals比较地址),导致given(custService.createCust(customer))的匹配条件不触发,Service方法返回null,最终响应体为空,触发json can not be null or empty异常。
修复方式:
- 使用
any(CustomerEntity.class)匹配任意CustomerEntity实例:given(custService.createCust(any(CustomerEntity.class))).willReturn(customer2); - 或者重写
CustomerEntity的equals和hashCode方法,确保属性一致时对象相等; - 也可以用
ArgumentCaptor捕获请求中的对象,再验证属性:ArgumentCaptor<CustomerEntity> captor = ArgumentCaptor.forClass(CustomerEntity.class); given(custService.createCust(captor.capture())).willReturn(customer2); // 后续可以验证captor.getValue()的属性是否符合预期
2. 确保返回对象包含ID值
测试中customer2必须明确设置id属性为1,否则返回的CustomerEntity没有id字段,JSON序列化后自然找不到$.id:
CustomerEntity customer2 = new CustomerEntity(); customer2.setId(1); // 必须设置id customer2.setName("John Doe"); // 其他属性也按预期设置
3. 检查请求路径是否匹配
测试中请求路径是/api/createCust,但Controller的@PostMapping是/createCust,路径不匹配会导致请求返回404,响应体为空,同样触发错误。将测试中的路径改为/createCust,或者在Controller类上添加@RequestMapping("/api")注解。
4. 实体类序列化问题
Spring MVC返回对象时依赖getter方法进行JSON序列化,如果CustomerEntity没有为id及其他属性添加getter方法,序列化后的JSON会缺失对应字段。为所有私有属性添加getter方法(必要时添加setter):
public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } // 其他属性的getter/setter
内容的提问来源于stack exchange,提问作者Rupesh SA
相关产品推荐
相关产品推荐

