如何使用Spring RestDocs验证无序数组的JSON响应
问题
我正在使用Spring RestDocs验证REST API。其中一个API会根据输入返回生成值数组,我需要验证响应中的生成值是否正确。
响应示例如下:
{ "hybrids": ["horsephant", "pussydog", "tigerbird"] }
由于元素顺序无关,下次调用API可能返回:
{ "hybrids": ["pussydog", "horsedonkey", "tigerbird"] }
我当前使用的RestDoc测试代码片段为:
.jsonPath("$.hybrids[0]").isEqualTo("pussydog") .jsonPath("$.hybrids[1]").isEqualTo("horsedonkey") .jsonPath("$.hybrids[2]").isEqualTo("tigerbird");
该测试仅在数组顺序恰好吻合时才能通过,请问如何修改测试以忽略元素顺序,让两种响应都能通过验证?
解决方案
方法1:使用containsExactlyInAnyOrder断言
直接获取整个数组集合,用Hamcrest匹配器断言集合包含指定的所有元素,且不关心顺序:
.jsonPath("$.hybrids").value(containsExactlyInAnyOrder("pussydog", "horsedonkey", "tigerbird"));
需提前导入Hamcrest匹配器:
import static org.hamcrest.Matchers.containsExactlyInAnyOrder;
方法2:结合长度验证与hasItems
如果只需确保目标元素全部存在,同时数组长度符合预期,可以拆分验证逻辑:
.jsonPath("$.hybrids.length()").isEqualTo(3) .jsonPath("$.hybrids").value(hasItems("pussydog", "horsedonkey", "tigerbird"));
hasItems仅检查元素存在性,结合长度验证可避免数组出现额外元素。需导入:
import static org.hamcrest.Matchers.hasItems;
方法3:转为集合后断言
将响应中的数组转为Java List,再用集合断言验证顺序无关的元素匹配:
List<String> hybrids = response.jsonPath().getList("$.hybrids"); assertThat(hybrids, containsInAnyOrder("pussydog", "horsedonkey", "tigerbird"));
这种方式脱离链式调用,更适合需要额外处理(如过滤、转换)的复杂验证场景。
内容的提问来源于stack exchange,提问作者Arc-E-Tect
相关产品推荐
相关产品推荐

