如何在初始化脚本中正确维护 Testcontainers 的数据?

Posted

技术标签:

【中文标题】如何在初始化脚本中正确维护 Testcontainers 的数据?【英文标题】:How to properly maintain data for Testcontainers in init script? 【发布时间】:2021-08-18 11:09:01 【问题描述】:

我正在使用 Testcontainers 加载一个 Dockerized 数据库,用于我的 Spring Boot 应用程序进行集成测试。我目前正在使用初始化脚本来加载所有数据:

CREATE TABLE public.table1 (
...
...
);

CREATE TABLE public.table2 (
...
...
);

这一切都很好。我也有自己的手动测试数据,我可以插入这些数据来测试不同的场景:

-- Data for pre-existing quiz
INSERT INTO public.table1 (id, prop1, prop2) values (1, 'a', 'b');
INSERT INTO public.table2 (id, prop1, prop2) values (1, 'c', 'd');
INSERT INTO public.table2 (id, prop1, prop2) values (2, 'e', 'f');

再次,一切正常,我正在使用 YAML 文件来读取模拟这些对象以用于我的测试

  table1s:
    first:
      id: 1
      prop1: a
      prop2: b
  table2s:
    first:
      id: 1
      prop1: c
      prop2: d
    second:
      id: 2
      prop1: e
      prop2: f

我可以将它们放入一个可以从 YAML 文件属性中读取的类中,以便用于我的测试类

public class Table1TestData 

    @Autowired
    private Environment env;

    private UUID id;
    private boolean prop1;
    private boolean prop2;

    public UUID getId() 
        return id;
    

    public void setId(UUID id) 
        this.id = id;
    

    public boolean getProp1() 
        return prop1;
    

    public void setProp1(String trial) 
        this.prop1 = prop1;
    

    ....

    public Table1TestData getFirstRowData()
        Table1HelperFactory ret = new Table1HelperFactory();
        ret.setId(UUID.fromString(env.getProperty("table1s.first.id")));
        ret.setProp1(env.getProperty("table1s.first.id"));
        ....
        return ret;
    
    ....


我在我的测试中使用这个助手作为一个自动装配的实体(特别是对于我的服务类):

public class Table1ServiceTest 

  @ClassRule
  public static PostgresContainer postgresContainer = PostgresContainer.getInstance();


  @Autowired
  Table1Service table1Service;

  @Autowired
  Table1TestData table1TestData;

  @Autowired
  MockMvc mockMvc;

  @Autowired
  ObjectMapper objectMapper;

  @BeforeAll
  private static void startup() 
    postgresContainer.start();
  


  @Test
  @DisplayName("Table 1 Service Test")
  @Transactional
  public void findTable1ById() throws Exception 
    Table1TestData testData = table1TestData.getFirstRowData();
    Table1 table1 = table1Service.findTable1ById(testData.getId());
    assertNotNull(table1);
    assertEquals(table1.getId(), testData.getId());
    assertEquals(table1.prop1(), testData.prop1());
    ....

  


但是,假设我必须将一个新列应用到 Table1(或任何表),然后我将新架构放入 init 脚本中。我现在必须手动转到这些插入语句中的每一个并放入一个带有值的新列(假设没有默认值),或者甚至说是否删除了一个列(即使它不一定影响类)。这最终变得很麻烦。

所以我的问题确实是,对于使用初始化脚本为容器化数据库填充测试数据的人来说,在不进行大量手动管理的情况下高效维护这些数据的最佳方法是什么?

【问题讨论】:

【参考方案1】:

我认为您可以利用 postgresql 的初始化脚本功能:只需将您的 sql 脚本放在 /docker-entrypoint-initdb.d 下(必要时创建目录),它将直接执行它们而无需任何编程工作。

您可以在此处查看示例: https://github.com/gmunozfe/clustered-ejb-timers-kie-server/blob/master/src/test/java/org/kie/samples/integration/ClusteredEJBTimerSystemTest.java

定义你的 postgresql 指向那个目录:

.withFileSystemBind("etc/postgresql", "/docker-entrypoint-initdb.d",
                                                        BindMode.READ_ONLY)

如果您希望每个测试使用不同的脚本,请查看这篇文章: https://www.baeldung.com/spring-boot-data-sql-and-schema-sql

【讨论】:

以上是关于如何在初始化脚本中正确维护 Testcontainers 的数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在节点脚本中重用 Angular 6 API 服务?

模块的初始

在部署弹性 beantalk 之前运行正确的脚本

如何在使用 Python 脚本登录时维护登录会话

JMeter - 如何在多个测试环境中运行多个线程组

如何使用单独的 .js 文件正确地将 Fancybox 初始化为 WordPress?