У меня есть приложение Spring-Boot и интеграционные тесты с использованием Cucumber и WireMock.
Выполнение тестов в обычном непараллельном режиме выполнения работает нормально и без каких-либо проблем, но при переключении на параллельный режим с помощью cucumber.execution.parallel.enabled as true начались сбои. Исключение:
com.github.tomakehurst.wiremock.common.JsonException:
{
"errors" : [ {
"code" : 10,
"source" : {
"pointer" : "/code"
},
"title" : "Error parsing JSON",
"detail" : "Unrecognized field \"code\" (class com.github.tomakehurst.wiremock.common.Errors), not marked as ignorable"
} ]
}
at com.github.tomakehurst.wiremock.common.JsonException.fromJackson(JsonException.java:53)
at com.github.tomakehurst.wiremock.common.Json.read(Json.java:60)
at com.github.tomakehurst.wiremock.client.HttpAdminClient.safelyExecuteRequest(HttpAdminClient.java:519)
at com.github.tomakehurst.wiremock.client.HttpAdminClient.executeRequest(HttpAdminClient.java:489)
at com.github.tomakehurst.wiremock.client.HttpAdminClient.executeRequest(HttpAdminClient.java:466)
at com.github.tomakehurst.wiremock.client.HttpAdminClient.addStubMapping(HttpAdminClient.java:146)
at com.github.tomakehurst.wiremock.client.WireMock.register(WireMock.java:414)
at com.github.tomakehurst.wiremock.client.WireMock.register(WireMock.java:409)
at com.github.tomakehurst.wiremock.client.WireMock.givenThat(WireMock.java:115)
at com.github.tomakehurst.wiremock.client.WireMock.stubFor(WireMock.java:119)
Должна ли WireMock.stubFor быть потокобезопасной операцией? Судя по исключению, похоже, нет. Если нет потокобезопасности, какие обходные пути возможны (синхронизировать/заблокировать все выполнения stubFor)?
Пример инициализации заглушки:
WireMock.stubFor(post(urlPathMatching("/test"))
.withRequestBody(equalToJson(..))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(..)));
WireMock создается следующим образом:
WireMockServer wireMock = new WireMockServer(options()
.port(8000)
.extensions(new ResponseTemplateTransformer(true))
.notifier(new ConsoleNotifier(true)));
wireMock.start();
configureFor(8000);
версия: com.github.tomakehurst:wiremock-jre8-standalone:2.33.0
Клиент и сервер Wiremock - в каких зависимостях maven они присутствуют? потому что теперь у меня есть только транзитивная зависимость от com.github.tomakehurst:wiremock-jre8-standalone
Не могу сказать, что вы не предоставили достаточно информации, чтобы воспроизвести вашу проблему. В какой-то момент Wiremock действительно переехал с com.github.tomakehurst на com.wiremock. Возможно, это и есть причина, но это всего лишь предположение.
Если вы начнете отладку с HttpAdminClient.safelyExecuteRequest, вы, вероятно, сможете увидеть, что сервер на самом деле отправляет обратно.
ок, спасибо, попробую разобраться. но главная сложность в том, что он работает без каких-либо проблем при непараллельном выполнении тестов.
Да, но сейчас вы не можете понять, что вызывает эту проблему. Иногда сначала нужно побрить Яка.
Проблема @M.P.Korstanje возникла из-за неправильного выбора порта сервера WireMock, выполненного из другого потока, и ответ не был получен с кодом ошибки 404. Поскольку этот ответ не от сервера WireMock, полезная нагрузка не была десериализована в класс Errors из библиотеки WireMock. Спасибо за попытку помочь и дать несколько полезных советов!
Поздравляем! Это было не то, чего я ожидал.




После замены класса com.github.tomakehurst.wiremock.client.HttpAdminClient в моем репозитории и добавления дополнительных журналов было обнаружено, что телом ответа во время выполнения определения заглушки является {"code":"404.null.55","message":"Not Found"}.
Проблема заключалась в том, что запрос был нацелен на неверный порт, он использовал порт по умолчанию 8080 вместо настроенного 8000. В моем случае порт 8000 был настроен для сервера WireMock и 8080 для Tomcat из теста Spring Boot.
Первоначально при запуске контекста Spring код настраивает сервер WireMock с портом 8000 из потока main следующим образом:
WireMockServer wireMock = new WireMockServer(options()
.port(8000)
.extensions(new ResponseTemplateTransformer(true))
.notifier(new ConsoleNotifier(true)));
wireMock.start();
configureFor(8000);
а позже WireMock.stubFor(..) вызывается из другого потока (из-за режима параллельного выполнения Cucumber). Из-за реализации внутри WireMock у него есть локальный поток defaultInstance, который должен быть дополнительно настроен с использованием соответствующего порта из вызванного потока.
Поэтому я обновил код, чтобы он вызывал WireMock.configureFor(8000); перед каждым вызовом WireMock.stubFor(..), чтобы гарантировать, что порт настроен для каждого требуемого потока, и это устранило проблему.
Первоначальное исключение, с которым я столкнулся как JsonException Unrecognized field 'code', связано с неправильной обработкой кода ошибки клиента 404 внутри HttpAdminClient, поскольку эта ошибка не с сервера Wire Mock, а может быть с любого другого сервера (действительно, это редкий случай, но все же может случиться).
Я либо открою проблему, либо внесу исправление в WireMock, чтобы иметь описательную ошибку с явным указанием используемого порта в случае кода ошибки 404, поэтому библиотека будет корректно обрабатывать такие случаи.
Обновлять:
Изменение вклада WireMock с описательным сообщением об исключении было объединено.
У вас есть две проблемы. Во-первых, ваши зависимости Wiremock несовместимы друг с другом. В результате ваш клиент Wiremock не распознает ошибку сервера Wiremock. Это вызывает ошибку, которую вы видите сейчас. Во-вторых, что вообще заставило сервер Wiremock отправить вам сообщение об ошибке. Вы хотите решить вторую задачу, но не сможете увидеть детали этой проблемы, пока не решите первую задачу.