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

Posted

技术标签:

【中文标题】有没有办法在 postgres 测试容器中删除所有表或截断【英文标题】:Is there a way to drop all tables or truncate inside a postgres testcontainer 【发布时间】:2021-05-02 22:58:46 【问题描述】:

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

公共类 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)
  


第二种情况失败,因为第一次测试中的一些“脏”仍在 db 容器上。 我尝试为每个测试停止/启动容器。 (非常非常慢的过程,有时我会出错,然后又非常慢)。

    @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 来清理数据库。我的意思是,我想要的只是为每个测试提供一个干净的环境。

【问题讨论】:

【参考方案1】:

创建一个名为 test_template 的模板测试数据库。

每次测试后,

    从测试数据库断开所有会话(PostgreSQL v13 不需要):

    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'test';
    

    删除数据库

    DROP DATABASE test;
    

    在 v13 中,使用附加的 FORCE 选项。

    创建一个新的测试数据库

    CREATE DATABASE test TEMPLATE test_template;
    

注意:您必须在 JDBC 驱动程序中启用自动提交,CREATE DATABASEDROP DATABASE 才能工作。

【讨论】:

你能举个例子吗? 我做到了,不是吗? 通过使用与 ATM 相同的方式 (createNativeQuery("DROP DATABASE db_name"); 我收到错误:启用执行更新/删除查询语句。 您是否收到 PostgreSQL 错误消息以及该无意义的消息,可能是嵌套异常?你启用自动提交了吗? 我的意思是,“无法执行...”未启用...呵呵

以上是关于有没有办法在 postgres 测试容器中删除所有表或截断的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用 Azure 门户从 CosmosDB 容器中清除所有文档?

如何在 Postgres 中删除表的所有索引?

从容器中删除所有碎片

SQL 中有没有办法将目录中包含的所有 .csv 导入我的 postgres 表? (窗口操作系统)

一个测试容器用于多个测试

从 Postgres 数据库中删除所有函数