微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决使用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
}

测试在所有这些情况下均可成功运行:

  • 单独运行测试
  • 顺序为:Test1,Test3,Test2
  • 顺序为:Test3,Test1,Test2
  • 顺序为:Test2,Test3,Test1
  • 顺序为:Test2,Test1,Test3

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

  • 顺序为:Test1,Test2,Test3
  • 顺序为:Test3,Test2,Test1

我已经研究了这个问题,它与Spring Application Context和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进行存根,但是应用程序其余调用将转到正在侦听端口1的WM1。

我已经尝试清除将@DirtiesContext添加到Test2的Application Context,因此它将迫使Spring加载第三个AC,但是它不起作用。但是,如果我将@DirtiesContext添加到Test1或将@DirtiesContext(classMode = BEFORE_CLASS)添加到Test3,它将起作用。我不需要此解决方案,因为我有其他测试,并且不能保证测试将按哪个顺序运行,因此,如果将其添加到Test3中,则稍后执行顺序将更改,另一个测试将失败。我想要一个真正的解决方案。

有什么想法吗?

解决方法

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

当 spring 缓存的测试上下文被重用时,wiremock 端口变回该上下文端口,但似乎错过了配置 WireMock 类默认服务器配置的某些步骤。我们必须在 WireMock.configureFor(port)@Before 方法中使用当前运行的上下文的端口调用 @BeforeEach。这意味着当我们执行 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);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。