在哪里使用Spring Boot启动集成测试数据库

时间:2019-01-02 13:32:30

标签: spring spring-boot

我们不是使用JUnit @ClassRule来为我们的集成测试数据库启动docker TestContainers,而是让Spring使用ApplicationContextInitializer s来实现。
好处:

    通过 TestContext 缓存(JUnit ClassRule使每个测试类启动一个新容器),
  • 对于maven模块中的所有“集成测试”类,仅启动一个容器。
  • 从IDE启动单个测试类时也可以工作(不同于ClassRule中的JUnit TestSuite
  • 结果属性会提前注入到上下文中:数据库IP,端口,凭据...这样,我们就不会覆盖bean(DataSourceSession等),我们使用相同的配置类作为生产应用程序
  • 创建的容器对象作为bean添加到上下文中,因此测试代码可以访问它

简化示例:

public class RedisContainerInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>, ApplicationListener<ContextClosedEvent> {

    private GenericContainer<?> container;

    @Override
    public void initialize(ConfigurableApplicationContext ctx) {
        container = new GenericContainer<>("redis:3.2.12-alpine").withExposedPorts(6379);
        container.start();

        // Inject properties
        TestPropertyValues props = TestPropertyValues.of(
            "spring.redis.host=" + container.getContainerIpAddress(),
            "spring.redis.port=" + container.getMappedPort(6379));
        props.applyTo(ctx);

        // Register this object as a bean, 
        // so testing code can access the container
        ctx.getBeanFactory().registerSingleton("redisContainer", this);

        // Make this instance receive Spring context "Close" events
        ctx.addApplicationListener(this);
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        container.close();
    }

    // getter, other irrelevant methods

}

问题:使用ApplicationContextInitializer可行,但这是否是“春季之道”?

如果没有,那么什么样的Spring Bean可以尽早加载以注入Spring Boot启动程序将使用的属性?

在某些时候,我们使用了Spring Cloud Bootstrap上下文,但是用户不需要Spring Cloud来运行集成测试。

0 个答案:

没有答案