如何在测试容器中填充数据?

How to populate data in testcontainers?

上下文:

我有一个非 Spring Boot 应用程序,我将其包装在 Spring 启动中以测试功能。碰巧代码在测试中有一个内存数据库,我想针对不同的数据库进行测试以重现生产环境。我决定使用 testcontainers 以保持所有现有测试不变。

问题:

我需要将数百万行加载到测试容器中。问题是在 testcontainers 时如何填充数据库?我发现了一个类似的问题 -> How to populate testcontainers? 但我仍然不知道如何在其中填充数据。

如何在 testcontainers 中填充数据?

DatabaseTestInitalizer.java 我用来实例化容器:

import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.testcontainers.containers.MSSQLServerContainer;

public class DatabaseTestInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    private MSSQLServerContainer mssqlServerContainer;

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        mssqlServerContainer = new MSSQLServerContainer();
        mssqlServerContainer.start();

        // This is solution for 1.x.x Spring Boot framework
        // Article for migration from 1.x.x to 2.x.x Spring Boot 
        EnvironmentTestUtils.addEnvironment(configurableApplicationContext.getEnvironment(),
                "spring.datasource.url=" + mssqlServerContainer.getJdbcUrl(),
                "spring.datasource.username=" + mssqlServerContainer.getUsername(),
                "spring.datasource.password=" + mssqlServerContainer.getPassword()
        );
    }
}

你有两个选择:

  1. 从 dockerfile 链接创建容器:testcontainer dockerfile Customize your MySQL Database in Docker
  2. 您可以使用 flyway 等数据库迁移工具,数据库将自动填充

当我使用类似的设置时,我实施了以下方法:

  1. 无论如何,我已经在 Flyway 中管理了与 spring 引导集成的架构。所有迁移都是与模式定义相关的迁移,不会对数据做任何事情。 我将它们放在 src/main/sesources/...(不是测试类路径)中 - 因为它们也与常规应用程序启动相关。

  2. 我为填充测试数据的测试创建了特殊迁移。这些迁移在我模块的 src/test/resources 下。 这些 "test" 迁移的编写方式总是在常规迁移之后开始。

  3. 我已将 Flyway 配置为在测试前启动,以便它填充测试数据。

毕竟,主要思想是将测试代码与数据生成分离。

它对我们有用 - 所以我可以推荐这种方法。

话虽如此,如果您正在使用 spring,还有其他方法:

  • 如果您使用的是 JPA,请在设置中添加数据 "manually"。打电话给这个 测试开始前的代码。
  • 使用 @Sql 注释 运行 带有测试数据的脚本。总而言之,这里有很多选项,阅读 this tutorial 了解更多信息

经过更严格的搜索后我可以使用 withInitScript 并将架构和数据定义到 init.sql 中,确保 db/init.sql 位于 test/resources 中文件夹。

它的工作原理如下:

public MSSQLServerContainer mssqlServerContainer = (MSSQLServerContainer) new MSSQLServerContainer()
            .withInitScript("db/init.sql")
            .withExposedPorts(1433);

在这种情况下,您不需要 Flyway