有没有办法删除所有表或在 postgres 测试容器内截断

问题描述 投票:0回答:2

我正在寻找一种方法来保持组件测试的独立性。 因此,为了实现这种行为,在某些测试中我需要有一个“干净的数据库”或至少一个“干净的表”。我仍然找不到在测试容器内执行此操作的方法。 所以这是我到目前为止所尝试过的: 我的容器设置类:

公共类 PostgreSqlTestContainer 实现 QuarkusTestResourceLifecycleManager {

public static final PostgreSQLContainer<?> POSTGRES = new PostgreSQLContainer<>("postgres:alpine");

@Override
public Map<String, String> start() {
    POSTGRES.start();         
    return some_db_config_as_per_doc;
}

@Override
public void stop() {        
    POSTGRES.stop();
}

这是测试类:

@QuarkusTest
@QuarkusTestResource(PostgreSqlTestContainer.class)
class UserResourcesTest {

  @Test
  scenario_one(){
     // create a new user
     // do some stuff (@POST.. check HTTP == 201) 
  }

  @Test
  scenario_two(){
     // create new user
     // do some stuff (@POST.. check HTTP == 201) (pass)
     // look for all users on database
     // do more stuff (@GET..  check HTTP == 200) (pass)
     // assert that only 1 user was found
     // since scenario_one should not interfere with scenario_two (fail)
  }

}

第二个场景失败,因为第一个测试中的一些“脏”仍然在数据库容器上。 我尝试为每个测试停止/启动容器。 (过程非常非常慢,有时我会收到错误,然后又非常慢)。

    @BeforeEach
    void setup(){
        PostgreSqlTestContainer.POSTGRES.stop();
        PostgreSqlTestContainer.POSTGRES.start();
    }

还尝试截断表/删除整个数据库:

    @Inject
    EntityManager entityManager;

    @BeforeEach
    private void rollBack(){
        truncate();
    }

    void truncate(){
      Query nativeQuery = entityManager.createNativeQuery("DROP DATABASE IF EXISTS db_name");
      nativeQuery.executeUpdate();
    }

我正在寻找解决此问题的方法,我只是想在每次测试之前使用

@BeforeEach
来清理数据库。我的意思是,我想要的只是每次测试都有一个干净的环境。

java postgresql junit5 quarkus testcontainers
2个回答
0
投票

创建一个名为

test_template
的模板测试数据库。

每次测试后,

  1. 断开所有会话与测试数据库的连接(PostgreSQL v13 不需要):

    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'test';
    
  2. 使用

    删除数据库
    DROP DATABASE test;
    

    在 v13 中,使用附加的

    FORCE
    选项。

  3. 使用

    创建一个新的测试数据库
    CREATE DATABASE test TEMPLATE test_template;
    

注意:您必须在 JDBC 驱动程序中启用自动提交才能使

CREATE DATABASE
DROP DATABASE
正常工作。


0
投票

你可以尝试一下:

  1. 从容器定义中删除 static 子句它将强制它在每次 start() 执行时创建容器。

    PostgreSQLContainer POSTGRES ....

  2. 你也可以删除@beforeach中的停止我认为这是没有必要的

  3. 您可以在启动提供模式sql的容器时创建表:

     PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer< ("postgres:14-alpine")
               .withDatabaseName("db")
               .withUsername("username")
               .withPassword("password")
               .withCopyFileToContainer(
                    MountableFile.forClasspathResource("/schema.sql"),
                    "/docker-entrypoint-initdb.d/"
               );
    
  4. 如果您想根据您的测试方法插入一些数据,您可以执行类似的操作并在测试开始时调用它:

     private void loadData(String scriptPath) {
         try {
             postgresContainer.copyFileToContainer(
                  MountableFile.forClasspathResource(scriptPath),
                  "/data/import.sql"
             );
             postgresContainer.execInContainer(
                  "psql",
                  "-U",
                  postgresContainer.getUsername(),
                  "-d",
                  postgresContainer.getDatabaseName(),
                  "-f",
                  "/data/import.sql"
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    
© www.soinside.com 2019 - 2024. All rights reserved.