我使用JsonPath测试API的REST端点。我的测试用例看起来像这样。
首先我创建新对象
class Item {
String name;
int id;
List<String> places;
}
String name = "Randomname" + new Random().nextLong();
JSONObject obj = new Item(name, 3, Arrays.asList("Rome3", "London3", "Paris3"));
post("/items").content(obj);
然后我得到所有项目的列表,并检查我刚创建的项目是否在列表中。
mockMvc.perform(get("/api/v1/test"))
.andExpect(jsonPath("$.data[*].name", hasItems("item 1", "item 2"))) // Fine
.andExpect(jsonPath("$.data[?(@.id == 1)].name", contains("item 1")))
.andExpect(jsonPath("$.data[?(@.id == 1)].places", contains(contains("Rome1", "London1", "Paris1"))))
.andReturn();
哪个有效,但我不认为我做得对,因为我有一个嵌套的contains(contains())
。 (我已经在本文末尾提供了完整的JSON响应。)
问题是因为JsonPath表达式返回一个列表,我需要使用列表匹配器。例如,而不是写这个
jsonPath("$.data[?(@.id == 1)].name", is("item 1"))
我需要像这样写
jsonPath("$.data[?(@.id == 1)].name", contains("item 1"))
因为JsonPath表达式将返回一个元素的JSON列表
[
"item 1"
]
哪个不是很糟糕,但是列表会变得更糟,例如试图检查我的变量位置中的字符串列表是否包含我想要的内容。返回的JSON是列表列表,因此这个JsonPath表达式
jsonPath("$.data[?(@.id == 1)].places"
将返回此
[
[
"Rome2",
"London3",
"Paris3"
]
]
所以它需要一个嵌套的hasItems
jsonPath("$.data[?(@.id == 1)].places", hasItems(hasItems("Rome1", "London1")))
在这方面工作,但这样做只是让我觉得我没有正确地做到这一点并且我错过了一些东西。
所以我的问题是,处理检查/匹配列表列表的适当方法是什么?
有没有更好的方法来验证端点返回的JSON?