Как проверить значение или другое значение в каждом элементе массива в теле?

Я проверяю тело ответа, проверяя, содержит ли каждое имя элемента или 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)))));

Как я могу проверить имя или panCode в теле с помощью hamcrest?


person Gabistic    schedule 10.10.2019    source источник


Ответы (2)


Причина, по которой ваш пример не работает, заключается в том, что hasProperty(java.lang.String propertyName, Matcher<?> valueMatcher) matcher работает с объектами JavaBean, а JsonPath представляет все как карту. Взгляните на описание этого метода из документа Hamcrest Matchers JavaDoc:

Создает сопоставление, которое сопоставляется, когда исследуемый объект имеет свойство JavaBean с указанным именем, значение которого удовлетворяет указанное сопоставление.

Когда вы работаете с ответом, используя 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)))));
person bhusak    schedule 14.10.2019
comment
Спасибо @bhusak за ответ, но он не работает Response body doesn't match expectation. Expected: every item is (map containing ["name"->a string containing "PAN"] or map containing ["panCode"->a string containing "PAN"]) Actual: [{"id":1000000002099,"name":"","panCode":"PANPL00002101","idAttachedDu":1000000008574},{"id":1000000002100,"name":"","panCode":"PANPL00002102","idAttachedDu":1000000008574},{"id":1000000001341,"name":"","panCode":"PANPL00001344","idAttachedDu":1000000004962}] - person Gabistic; 16.10.2019
comment
Привет @Gabistic! Просто исправил это, добавив путь в тело. Попробуй это сейчас - person bhusak; 16.10.2019

Поскольку тело ответа представляет собой прямой массив json, следующий подход будет работать.

Во-первых, лучше иметь класс, представляющий один элемент массива, например 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>

Наконец, получите ответ, преобразуйте его в массив Pans, затем подтвердите. (при необходимости измените 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"))))
    );
}
person Ruwanka Madhushan    schedule 13.10.2019
comment
Я когда-либо пробовал ваше предложение, и оно сработало. Но я хотел бы знать, почему предыдущий синтаксис не - person Gabistic; 14.10.2019
comment
Вы не опубликовали, как вы создаете ответ. Чтобы hasProperty сопоставитель работал, ему требуется объект определенного типа. Просто ответ возвращает карту в вашем случае (hasEntry может работать, но я не смог этого сделать), и поскольку его необработанный массив jsonPath. getList("$") требуется для правильного анализа массива в теле. - person Ruwanka Madhushan; 15.10.2019