如何验证正文中每个数组项中的值或另一个值?

How to validate either value or another value in every array items in body?

我正在通过检查每个项目名称或 panCode 中是否包含 "PAN".

来验证响应正文

验证每个项目名称或 panCode 是否包含 "PAN" 并且我有错误

预期:每个项目都是(hasProperty("name",一个包含"PAN"的字符串)或hasProperty("panCode",一个包含"PAN"的字符串))

实际:[{"id":1000000002099,"name":"","panCode":"PANPL00002101","idAttachedDu":1000000008574},{"id":1000000002100,"name":"","panCode":"PANPL00002102","idAttachedDu":1000000008574}]

response.then().assertThat().body(everyItem(
                either(hasProperty("name", containsString(criteria)))
               .or(hasProperty("panCode", containsString(criteria)))));

如何使用 hamcrest 验证正文中的名称或 panCode?

由于响应主体是直截了当的 json 数组,因此可以使用以下方法。

首先最好让class代表数组的一项,比如Pan

public static class Pan
{
    private long id;
    private String name;
    private String panCode;
    private String idAttachedDu;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPanCode() {
        return panCode;
    }

    public void setPanCode(String panCode) {
        this.panCode = panCode;
    }

    public String getIdAttachedDu() {
        return idAttachedDu;
    }

    public void setIdAttachedDu(String idAttachedDu) {
        this.idAttachedDu = idAttachedDu;
    }
}

添加jackson或gson反序列化json成此类对象(这里使用jackson)

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.10.0</version>
</dependency>

终于得到响应,将其转换为 Pan 的数组,然后断言。 (请根据需要更改 url,额外提示:对本地模拟服务器使用 mockoon

@Test
void panRestAssuredTest() {

    Response response = given().headers("Content-Type", ContentType.JSON, "Accept", ContentType.JSON).
            when().get("http://localhost:8000/restassured").
            then().contentType(ContentType.JSON).extract().response();

    List<Pan> pans = response.jsonPath().getList("$", Pan.class);

    assertThat(pans, everyItem(
            either(hasProperty("panCode", containsString("PAN")))
            .or(hasProperty("name", containsString("PAN"))))
    );
}

您的示例不起作用的原因是 hasProperty(java.lang.String propertyName, Matcher<?> valueMatcher) 匹配器正在处理 JavaBean 对象,而 JsonPath 将所有内容都表示为 Map。查看 Hamcrest 的 Matchers JavaDoc 中此方法的描述:

Creates a matcher that matches when the examined object has a JavaBean property with the specified name whose value satisfies the specified matcher.

当您使用 body(Matcher<?> matcher, Matcher<?>... additionalMatchers) 处理响应时,它会将响应 JSON 转换为映射,JavaBean 匹配器不能在此处应用。而是尝试使用适用于 java.util.Map 的匹配器。

以下是您的示例的工作原理:

response.then().assertThat()
    .body("$", everyItem(either(hasEntry(equalTo("name"), containsString(criteria)))
        .or(hasEntry(equalTo("panCode"), containsString(criteria)))));