使用 WireMock 的 Spring JUnit 测试中的多个应用程序上下文
Posted
技术标签:
【中文标题】使用 WireMock 的 Spring JUnit 测试中的多个应用程序上下文【英文标题】:Multiple Application Contexts in Spring JUnit test with WireMock 【发布时间】:2020-09-25 11:36:30 【问题描述】:我有以下场景:
@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 进行了存根,但应用程序的其余调用将转到 WM1,它正在侦听端口 1。
我已经尝试清理将@DirtiesContext
添加到Test2 的应用程序上下文,因此它会强制Spring 加载第三个AC,但它不起作用。但是,如果我将 @DirtiesContext
添加到 Test1 或将 @DirtiesContext(classMode = BEFORE_CLASS)
添加到 Test3 ,它就可以工作。我不想要这个解决方案,因为我有其他测试并且无法保证测试将以什么顺序运行,所以如果我将它添加到 Test3,那么稍后执行顺序将改变,另一个测试将失败。我想要一个真正的解决方案。
有什么想法吗?
【问题讨论】:
每个 AC 是否需要单独的 WireMock 实例?如果没有,您能否启动一个单一的 WireMock 实例并让所有 AC 指向它? 不,这就是@AutoConfigureWireMock 的工作方式。它为每个 AC 创建一个新的 WM 实例。我可以按照你的建议做,但是我必须自己控制一切,然后使用注释就没有意义了。如果我找不到解决方案,这就是我要走的路。 【参考方案1】:不确定您是否找到了解决方案,但这是我解决此问题的方法。
当 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 的 Spring JUnit 测试中的多个应用程序上下文的主要内容,如果未能解决你的问题,请参考以下文章