wiremock jsonPath и целочисленные значения

Вопрос или проблема

Я оцениваю Wiremock для использования в нашем проекте

Нужна помощь в понимании того, как сгенерировать целочисленное поле в ответе, извлечённом из запроса (оба являются JSON). Пример сопоставлений заглушек:

String mapping = """
            {
              'request': {
                'method': 'POST',
                'urlPathTemplate': '/v1/persons/{personId}'
              },
                        
              'response': {
                'status': 200,
                'jsonBody':  {
                    'name' : "{{jsonPath request.body '$.name'}}",
                    'age' : "{{jsonPath request.body '$.age'}}",
                    'id' :  '{{request.path.personId}}'
                 },
                'headers': {
                    'Content-Type': 'application/json'
                }
              }
            }
            """;

Я ожидаю отправить запрос на

POST: http://localhost:8080/v1/persons/123456789

BODY:

{
   'name' : 'Alice',
   'age'  : 25
}

И мой ответ ожидается следующим образом:

{
   "name" : "Alice",
   "age"  : 25,
   "id"   : "123456789"
}

Тем не менее, фактическое тело ответа, которое я получаю, немного отличается, значение возраста является строкой:

{
   "name" : "Alice",
   "age"  : "25",                    <-- Это не то, что я хочу
   "id"   : "123456789"
}

Вот код, который я использую (обычный java + wiremock 3.9.1 – последний доступный на данный момент):

 WireMockServer ws = new WireMockServer(
                wireMockConfig()
                        .port(8080)
                        .globalTemplating(true)
        );

        ws.addStubMapping(StubMapping.buildFrom(mapping)); // моя строка сопоставления, определенная выше
        ws.start();
        var req = HttpRequest.newBuilder()
                .uri(new URI("http://localhost:8080/v1/persons/123456789"))
                .POST(HttpRequest.BodyPublishers.ofString("""
                        {
                          'name' : 'Alice',
                          'age' : 25
                        }
                        """)).build();
        var client = HttpClient.newHttpClient();
        var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println("Получено тело: " + resp.body());
        ws.shutdownServer();

Я не смог найти соответствующий пример в документации Wiremock для этого случая, поэтому спрашиваю о помощи. Также возможно ли отобразить поле ‘id’ как число (вероятно, решение будет похожим), несмотря на то, что оно было извлечено из пути запроса, а не из тела

Ответ или решение

Использование WireMock для работы с JSON и целыми числами

На текущий момент, вы столкнулись с проблемой при использовании библиотеки WireMock для создания моков RESTful API. В частности, вы хотите вернуть целое число из вашего JSON-запроса, но получаете строковое значение. Давайте разберем ваш случай подробнее и предложим решения.

Текущая ситуация

Ваша конфигурация WireMock определяет мэппинг для ответа, который должен включать поля name, age и id. Вы ожидаете, что поле age будет целым числом, однако, в ответе оно возвращается как строка ("25"). Это происходит потому, что WireMock по умолчанию обрабатывает значения как строки, когда они извлекаются из JSON.

Решение проблемы с извлечением целых чисел

Чтобы гарантировать, что значение age возвращается как целое число, вам нужно использовать специальный синтаксис, который позволяет производить преобразования. К сожалению, в версии WireMock 3.9.1 нет встроенной функции для конвертации строк в числа непосредственно в шаблонах.

Тем не менее, вы можете воспользоваться следующим обходным решением:

  1. Выделите необходимые поля запроса как строки.
  2. Прямо укажите ожидаемые значения или используйте кастомные функции, если это необходимо.

Пример корректной конфигурации WireMock

Вот пример настройки, который вы можете использовать:

String mapping = """
{
  "request": {
    "method": "POST",
    "urlPathTemplate": "/v1/persons/{personId}"
  },
  "response": {
    "status": 200,
    "jsonBody": {
      "name": "{{jsonPath request.body '$.name'}}",
      "age": {{jsonPath request.body '$.age'}},  // Убираем кавычки
      "id": {{request.path.personId}} // Убираем кавычки для целого числа
    },
    "headers": {
      "Content-Type": "application/json"
    }
  }
}
""";

В этом примере:

  • Поле age больше не заключено в кавычки, что позволит WireMock интерпретировать его как число.
  • Поле id также возвращается как целое число, так как оно напрямую соотносится с параметром пути.

Пример тестирования

Вот как будет выглядеть тестирование вашего мока:

WireMockServer ws = new WireMockServer(
    wireMockConfig()
        .port(8080)
        .globalTemplating(true)
);

ws.addStubMapping(StubMapping.buildFrom(mapping)); // добавляем маппинг
ws.start();

var req = HttpRequest.newBuilder()
    .uri(new URI("http://localhost:8080/v1/persons/123456789"))
    .POST(HttpRequest.BodyPublishers.ofString("""
        {
            "name": "Alice",
            "age": 25
        }
    """)).build();

var client = HttpClient.newHttpClient();
var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println("Got a body: " + resp.body()); // Ожидаемый ответ

ws.shutdownServer();

Заключение

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

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

Оцените материал
Добавить комментарий

Капча загружается...