在 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 中使用保存点进行测试的嵌套事务的主要内容,如果未能解决你的问题,请参考以下文章
在 Docker 上使用 Nginx、uWSGI 和 Postgres 配置 Django