Вопрос или проблема
Я оцениваю 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 нет встроенной функции для конвертации строк в числа непосредственно в шаблонах.
Тем не менее, вы можете воспользоваться следующим обходным решением:
- Выделите необходимые поля запроса как строки.
- Прямо укажите ожидаемые значения или используйте кастомные функции, если это необходимо.
Пример корректной конфигурации 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 на работу с типами данных могут потребовать использования каких-либо обходных путей, поскольку преобразование типов (например, из строки в число) не поддерживается напрямую.
Надеюсь, это поможет разрешить вашу проблему. Если у вас возникнут дополнительные вопросы или потребуется дальнейшая помощь, не стесняйтесь обращаться.