在 clojure.jdbc 和 postgres 中使用保存点进行测试的嵌套事务

Posted

技术标签:

【中文标题】在 clojure.jdbc 和 postgres 中使用保存点进行测试的嵌套事务【英文标题】:Nested transactions using savepoints for tests in clojure.jdbc and postgres 【发布时间】:2020-08-06 11:53:29 【问题描述】:

在我的单元测试中,我有一个夹具,它创建一个回滚事务,以便在我的测试运行后清理数据库。它看起来像这样:

(defn with-rollback [test-fn]
  (let [db-conn    (db/connect db/test-pg-db)]
    (jdbc/with-db-transaction [txn db-conn :isolation :serializable]
      (jdbc/db-set-rollback-only! txn)
      (-> (mount/only [#'db/db])
          (mount/swap #'db/db txn)
          (mount/start))
      (test-fn)
      (mount/stop))
    (db/disconnect db-conn)))

然后在测试中我做(use-fixtures :each fixtures/with-rollback)

这很好用,除了在我想测试错误条件实际上回滚事务的测试中。例如,我想测试当对外部服务的请求失败时,我不会向数据库写入任何内容。

对于我的用例,有没有办法获得类似于嵌套事务的行为?我有一个想法,用在事务打开和回滚时创建保存点的东西来覆盖 jdbc/db-transaction* 函数捕捉到异常时到最近的一个 - 但我永远无法让它工作。感谢任何帮助!

【问题讨论】:

【参考方案1】:

我也在努力解决这个问题,并最终决定采用一种解决方法,即为“正常”测试和事务测试提供单独的文件。这样就可以使用单独的灯具。

因此,您可以为正常测试使用回滚夹具,为事务测试使用清除/截断夹具。截断具有较大的性能成本,因此应谨慎使用夹具。

这里是截断夹具的实现。假设使用的架构是public,并且在schema_migrations 表中存储了一些关于数据库迁移的数据,这些数据应该保持不变。

(defn truncate-db [tests]
  (tests)
  (jdbc/execute! db-conn
                 "DO $$ BEGIN
                    EXECUTE 'TRUNCATE TABLE '
                    || (SELECT string_agg(table_name::text, ',')
                        FROM information_schema.tables
                        WHERE table_schema = 'public'
                        AND table_type = 'BASE TABLE'
                        AND table_name != 'schema_migrations')
                    || ' CASCADE';
                  END; $$;"))

【讨论】:

我也是这样做的。自动截断所有表格的好方法

以上是关于在 clojure.jdbc 和 postgres 中使用保存点进行测试的嵌套事务的主要内容,如果未能解决你的问题,请参考以下文章

Clojure jdbc 创建复合主键

如何使用 clojure jdbc 执行?

连接数据库结果的下划线Clojure映射键

在 Docker 上使用 Nginx、uWSGI 和 Postgres 配置 Django

Spring 事务和 postgres(VACUUM,在事务外部运行)

如何将strapi、graphql和postgres连接在一起?