使用WireMock测试Spring JUnit中的多个应用程序上下文



我有以下场景:

@Transactional
@SpringBootTest
@ActiveProfiles("test")
@AutoConfigureMockMvc
@AutoConfigureWireMock(port = 0)
public abstract class IntegrationTest {
}
public class Test1 extends IntegrationTest {
// Tests that use WireMock
}
@ActiveProfiles("specific-case-test") // This causes another Application Context to be created.
public class Test2 extends IntegrationTest {
// Tests that use WireMock
}
public class Test3 extends IntegrationTest {
// Tests that use WireMock
}

测试在所有这些场景中都能成功运行:

  • 单独运行测试
  • 按顺序:测试1、测试3、测试2
  • 按顺序:测试3、测试1、测试2
  • 按顺序:测试2、测试3、测试1
  • 按顺序:测试2、测试1、测试3

在所有这些情况下运行的最后一个测试失败:

  • 按顺序:Test1、Test2、Test3
  • 按顺序:测试3、测试2、测试1

我已经调查了这个问题,它与Spring应用程序上下文和WireMock有关。

发生了什么事?让我们考虑一下测试是按以下顺序运行的:Test1, Test2, Test3

Test1运行时,会创建一个应用程序上下文(AC1(,并在端口1上设置一个WireMock服务器(WM1(。端口1设置为AC1(wiremock.server.port(,WM1连接到测试线程。所有测试均通过。

Test2运行时,会创建另一个应用程序上下文(AC2(,并在端口2上设置一个新的WireMock服务器(WM2(。端口2设置为AC2(wiremock.server.port(,WM2连接到测试线程,取代WM1。所有测试均通过。

Test3运行时,它会重用AC1,这会导致测试失败,并显示消息:404 Not Found: [No response could be served as there are no stub mappings in this WireMock instance.]。应用程序状态为wiremock.server.port为1(来自AC1(,WM2附加到测试线程。因此,对WM2进行存根处理,但应用程序rest调用将转到正在端口1上侦听的WM1。

我已经尝试过清理向Test2添加@DirtiesContext的应用程序上下文,所以它会强制Spring加载第三个AC,但它不起作用。但是,如果我将@DirtiesContext添加到Test1,或者将@DirtiesContext(classMode = BEFORE_CLASS)添加到Test3,它就可以工作了。我不想要这个解决方案,因为我还有其他测试,无法保证测试的运行顺序,所以如果我将其添加到Test3中,那么稍后执行顺序将更改,另一个测试将失败。我想要一个真正的解决方案。

有什么想法吗?

不确定您是否找到了解决方案,但以下是我解决此问题的方法。

当重用spring缓存的测试上下文时,wiremock端口会变回该上下文端口,但似乎错过了配置WireMock类默认服务器配置的某些步骤。我们必须使用当前运行上下文的端口在@Before@BeforeEach方法中调用WireMock.configureFor(port)。这意味着,当我们进行stubFor方法调用时,正确的WireMock端口被击中,服务器正确地配置了我们的存根,请确保在任何重置之前也进行了配置。

@Autowired
private Environment environment;
private String getWiremockServerPort() {
// Get the auto configured port property from the current Spring contexts environment
return environment.getProperty("wiremock.server.port");
}
@BeforeEach
private void configureWireMockPortToMatchEnvironmentContext() {
int contextEnvironmentPort = Integer.parseInt(getWiremockServerPort());
configureFor(contextEnvironmentPort);
}

如果您以这种方式创建Wiremock存根:

stubFor(post(urlEqualTo(CALLBACK))
.willReturn(aResponse().withStatus(202))
);

在使用静态方法"的情况下;stubFor&";从com.github.tomakehurst.wiremock.client.wiremock,您可以尝试在测试类中添加一个自动连线的WiremockServer对象:

@Autowired
protected WireMockServer wireMockServer;

然后将存根创建替换为:

wireMockServer.stubFor(post(urlEqualTo(CALLBACK))
.willReturn(aResponse().withStatus(202))
);

其中使用了com.github.tomakehurst.wiremock.WireMockServer.中的非静态方法

就我而言,这解决了问题。

最新更新