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

标签 java spring spring-boot integration-testing wiremock

我有以下场景:

@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) 并设置 WireMock 服务器 (WM1),假设在端口 1 上。端口 1 设置为 AC1 ( wiremock.server.port ) 并且 WM1 附加到测试线程。所有测试通过。
    Test2运行,创建另一个应用程序上下文 (AC2) 并设置一个新的 WireMock 服务器 (WM2),比方说,在端口 2 上。端口 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 附加到测试线程。因此, stub 发生在 WM2 上,但应用程序的其余调用将转到 WM1,WM1 正在监听端口 1。
    我已经尝试清理应用程序上下文添加 @DirtiesContext到 Test2,所以它会强制 Spring 加载第三个 AC,但它不起作用。但是,如果我添加 @DirtiesContext到 Test1 或 @DirtiesContext(classMode = BEFORE_CLASS)到Test3它的工作原理。我不想要这个解决方案,因为我有其他测试,并且无法保证测试的运行顺序,所以如果我将它添加到 Test3,那么稍后执行顺序将改变,另一个测试将失败。我想要一个真正的解决方案。
    有任何想法吗?

    最佳答案

    不确定您是否找到了解决方案,但这是我解决此问题的方法。
    当 spring 缓存的测试上下文被重用时,wiremock 端口变回该上下文端口,但似乎错过了配置 WireMock 的某些步骤。类默认服务器配置。我们不得不打电话WireMock.configureFor(port)@Before@BeforeEach方法与当前运行的上下文的端口。这意味着当我们做 stubFor方法调用然后正确的 WireMock 端口被命中并且服务器正确配置了我们的 stub ,请确保在任何重置之前也进行此配置。

    @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);
    }
    

    关于java - 使用 WireMock 测试 Spring JUnit 中的多个应用程序上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64063372/

    相关文章:

    java - 为什么我必须投一个按钮?

    java - 您可以同时写入套接字输入和输出流吗?

    java - 在线程运行时中断它;下一次中断的影响是什么?

    java - 通过 checkmarx 中的错误消息暴露信息

    java - JComboBox.setSelectedItem() 问题

    java - Spring REST 模板 POST

    spring 工具套件无法在 tomcat 上部署示例 Web 服务

    java - 如何在没有环境的情况下读取 application.properties 文件

    java - 使用 Redis 在 Spring Boot 中将对象添加到 Http Session 失败

    java - 从端点调用时,Spring Boot 获取 UTC+1 而不是 GMT