如何为含字符串与数组的JSON编写MockMVC测试并解决断言异常
看起来你在MockMVC测试里遇到了JSONPath断言的问题,我来帮你梳理下问题所在和解决办法:
首先看你给出的JSON数据,accounts是一个数组(用方括号包裹),而不是单个JSON对象。你最初写的$.accounts.id是直接从数组上取属性,这肯定不行——数组本身没有id属性,只有数组里的元素才有。
你尝试用$.accounts[0].id还是报错,大概率是两个原因:要么是接口返回的accounts数组和你预期的结构不一致,要么是你测试里的其他断言(比如根节点属性数量的断言)先失败了,导致你误以为是这个路径的问题。
修正后的测试代码
我调整了你的测试,修正了JSONPath的写法,同时优化了断言顺序,这样更容易定位问题:
@Test public void testJson() throws Exception { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); mockMvc.perform(get("/acc/1") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) // 先确认accounts数组的长度是1,确保数组里有元素 .andExpect(jsonPath("$.accounts", Matchers.hasSize(1))) // 通过索引[0]访问数组第一个元素,再断言它的属性 .andExpect(jsonPath("$.accounts[0].id", Matchers.is(1))) .andExpect(jsonPath("$.accounts[0].balance", Matchers.is("$1000"))) .andExpect(jsonPath("$.accounts[0].accNbr", Matchers.is("12345"))) .andExpect(jsonPath("$.accounts[0].custid", Matchers.is("1"))) // 根节点一共有6个属性(id、firstName、lastName、mobile、email、accounts),你之前写的4是错误的 .andExpect(jsonPath("$.*", Matchers.hasSize(6))); }
关键细节说明
- 数组访问的正确姿势:对于JSON数组,必须通过
[索引]来访问内部元素,比如$.accounts[0]就是取数组的第一个元素,之后再链式访问它的属性(比如.id)。 - 断言顺序很重要:先验证整体状态(比如HTTP状态码),再验证容器的基本情况(比如数组大小),最后验证具体元素的属性。这样如果前面的断言失败,你能快速定位是数组为空,还是结构不对。
- 修正根节点属性数量:你之前断言
$.hasSize(4)是错误的,你的示例JSON根节点有6个属性,这个错误的断言会先导致测试失败,让你误以为是$.accounts[0].id的问题。
额外排查技巧
如果还是报错,建议先打印出接口的实际返回内容,确认结构是否和你预期的一致:
在测试里添加andDo(print()),可以输出完整的请求和响应详情:
mockMvc.perform(get("/acc/1") .accept(MediaType.APPLICATION_JSON)) .andDo(print()) // 打印请求响应信息,方便排查 .andExpect(status().isOk()) // ... 后续断言
这样你就能清楚看到返回的JSON结构,确认是否和你提供的示例一致。
内容的提问来源于stack exchange,提问作者kadi nana
相关产品推荐
相关产品推荐

