Wiremock: как сопоставить запрос JSON, у которого НЕТ определенного свойства?

Я пытаюсь имитировать вызов API, который принимает тело JSON в POST и имеет два возможных ответа:

  1. если тело содержит свойство SearchCenter, ответьте ответом A
  2. если тело НЕ содержит SearchCenter, ответьте ответом B

В главе Request Matching документации Wiremock показано только, как положительно соответствует JSON, он не показывает, как сопоставить отсутствующие свойства.

Пример запроса с SearchCenter:

{
    "GeoCoordinatesResponseFormat": "DecimalDegree",
    "ProviderID": "bla bla",
    "SearchCenter": {
        "GeoCoordinates": {
            "DecimalDegree": {
                "Latitude": "{{search_lat}}",
                "Longitude": "{{search_lon}}"
            }
        },
        "Radius": {{search_radius}}
    }
}

Пример запроса без SearchCenter:

{
    "GeoCoordinatesResponseFormat": "DecimalDegree",
    "ProviderID": "bla bla"
}

person Dimitri De Franciscis    schedule 12.05.2020    source источник


Ответы (2)


Изменить: возможно, я забегал вперед - я думаю, что есть более простое решение для сопоставления. Вы можете использовать отрицательное соответствие с регулярным выражением . (Отрицательный взгляд вперед) Я все еще думаю, что предпочитаю метод приоритетов.

stubFor(any(urlPathEqualTo("/some-endpoint"))
    .withRequestBody(matchingJsonPath("$.?!SearchCenter"))
    .willReturn(ok("Body does not contain Search Center"));

stubFor(any(urlPathEqualTo("/some-endpoint"))
    .withRequestBody(matchingJsonPath("$.SearchCenter"))
    .willReturn(ok("Body does contain Search Center"));

Это можно сделать двумя способами. Первый будет использовать сопоставление / не сопоставление регулярных выражений. Предполагая, что вы используете заглушки ...

stubFor(any(urlPathEqualTo("/some-endpoint"))
    .withRequestBody(notMatching("\"SearchCenter\": \{ .* \}"))
    .willReturn(ok("Body does not contain Search Center"));

stubFor(any(urlPathEqualTo("/some-endpoint"))
    .withRequestBody(matchingJsonPath("$.SearchCenter"))
    .willReturn(ok("Body does contain Search Center"));

Это выполняет сопоставление регулярного выражения при отсутствии сопоставления для проверки того, не существует ли поле, а затем сопоставление пути JSON для случая, когда поле действительно существует. (Я не тестировал фактический код, поэтому для сопоставления регулярных выражений / пути JSON может потребоваться некоторая настройка.)

Однако я думаю, что лучшим решением было бы, чтобы более конкретное совпадение возвращало один ответ, а менее конкретное совпадение возвращало другой ответ. Мы можем добиться этого с помощью приоритетов.

stubFor(any(urlPathEqualTo("/some-endpoint"))
    .atPriority(1)
    .withRequestBody(matchingJsonPath("$.SearchCenter"))
    .willReturn(ok("Body does contain Search Center"));

stubFor(any(urlPathEqualTo("/some-endpoint"))
    .atPriority(2)
    .willReturn(ok("Body does not contain Search Center"));

Здесь можно найти информацию о приоритетах. Главное в приоритетах заключается в том, что они заставляют WireMock проверять одни совпадения раньше других. В этом случае мы собираемся проверить, содержит ли тело запроса нужное нам поле («Центр поиска»), и если оно есть, мы вернем совпадение. Если бы у нас были другие заглушки с таким же приоритетом (1), они также были бы проверены перед переходом к следующему приоритету. В случае, если поле, по которому мы хотим сопоставить, не найдено, мы переходим к следующему приоритету. Поскольку заглушка с приоритетом 2 не обязательно должна соответствовать пути JSON в теле запроса, мы сопоставим.

Я предпочитаю устанавливать приоритеты по сравнению с двойным совпадением просто потому, что мне нравится «резервное» поведение, которое обеспечивает общая заглушка, когда любые вызовы «/ some-endpoint» будут выполняться с общим ответом.

person agoff    schedule 12.05.2020
comment
Мне больше нравится решение Priority по двум причинам: 1) регулярные выражения трудно читать и поддерживать и 2) использование приоритетов лучше отражает то, как маршруты обрабатываются серверной частью. - person Dimitri De Franciscis; 13.05.2020

Чтобы сопоставить отсутствующее свойство JSON, вы можете использовать оператор matchingJsonPath в сочетании с absent(), например:

.withRequestBody(matchingJsonPath("$.SearchCenter", absent()))
person Ivan Koryshev    schedule 08.07.2020