我有Spring—Boot应用程序和集成测试,使用Cucumber和WireMock. 在常规的非并行执行模式下执行测试工作正常,没有任何问题,但是当切换到并行执行模式时,测试开始失败.例外情况:

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的所有执行)?

stub初始化示例:

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

推荐答案

在我的repo中替换类com.github.tomakehurst.wiremock.client.HttpAdminClient并添加额外的日志(log)之后,发现stub定义执行期间的响应主体是{"code":"404.null.55","message":"Not Found"}. 问题是请求针对错误的端口,它使用了默认端口8080而不是配置的8000.在我的例子中,端口8000被配置为WireMock服务器和8080从Spring Boot测试.

最初,当Spring上下文启动时,代码从线程main以以下方式配置WireMock服务器:

WireMockServer wireMock = new WireMockServer(options()
    .port(8000)
    .extensions(new ResponseTemplateTransformer(true))
    .notifier(new ConsoleNotifier(true)));
wireMock.start();
configureFor(8000);

然后,WireMock.stubFor(..)从另一个线程调用(由于Cucumber的并行执行模式).由于WireMock内部的实现,它具有线程本地defaultInstance,该线程本地defaultInstance应该另外配置有来自调用线程的适当端口.

因此,我更新了代码,以便在每次调用WireMock.stubFor(..)之前调用WireMock.configureFor(8000);,以确保每个所需线程都配置端口,它修复了这个问题.

我遇到的初始异常是由于没有正确处理HttpAdminClient内部的404客户端错误代码,因为这个错误不是来自Wire Mock服务器,而是可能来自任何其他服务器(事实上,这是一个罕见的情况,但仍然可能发生). 我要么打开一个问题,要么向WireMock提供一个修复,以在404错误代码的情况下显式指定使用的端口,因此库将优雅地处理这种情况.

Java相关问答推荐

如何让TaskView总是添加特定的列来进行排序?

将linkedHashMap扩展到Java中的POJO类

Annotation @ Memphier无法正常工作,并表示:class需要一个bean,但找到了2个bean:

屏蔽字母数字代码的Java正则表达式

使用意向过滤器从另一个应用程序启动服务

当涉及到泛型时,类型推理在Java中是如何工作的?

什么是Java原子属性的正确getter和setter

测试期间未执行开放重写方法

如何从错误通道回复网关,使其不会挂起

基于接口的投影、原生查询和枚举

匹配一组字符或另一组字符

在处理2个映射表时,没有更多的数据可从套接字读取

我如何为我的Java抵押贷款代码执行加薪操作(&Q)

从Spring6中的JPMS模块读取类时出现问题

AWS Java SDK v2.x中没有setObjectAcl方法

我的代码是线程安全的吗?[Java、CAS、转账]

Java KeyListener不工作或被添加

如何通过gradle命令行从build.gradle获得Java targetCompatibility

SonarQube在合并升级到java17后对旧代码提出错误

关于正则表达式的一个特定问题,该问题与固定宽度负向后看有关