gpt4 book ai didi

ruby-on-rails - 自定义事务不适用于 rspec 中的 database_cleaner

转载 作者:行者123 更新时间:2023-12-04 10:52:39 26 4
gpt4 key购买 nike

在我们使用 MySql 的 Rails 4.0 应用程序中,我们使用 rspec 和配置了策略的 database_cleaner gem :transaction 来为每个测试用例清理我们的数据库。如果我们有自定义事务,应该回滚,它不起作用。

没有 database_cleaner gem 并且只使用标准方式:

config.use_transactional_fixtures = true

一切正常。但是为了使用 JavaScript 运行特性测试,我们需要 database_cleaner 将夹具删除策略更改为 :truncation。

我们如何将 database_cleaner 与自定义事务一起使用,为什么它与标准的 rspec 事务策略不同?

最佳答案

问题是 database_cleaner 在测试结束时调用 ActiveRecord.rollback —— 您也在代码中使用它。 InnoDB/MySQL 不支持真正的嵌套事务,因此代码中的嵌套事务不会真正被视为事务,除非它们被明确调用来这样做。

考虑这个块(来自 ActiveRecord 文档):

User.transaction do
User.create(username: 'Kotori')
User.transaction do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback
end
end

您希望在 Rollback 调用之后发生什么?您希望它回滚 Nemu 用户,而将 Kotori 留给您,对吗?好吧,实际上发生的是 Kotori 和 Nemu 都被创造出来了。回滚不会触发,因为您处于嵌套事务中(并且 AR 目前只关心父事务)并且父事务(具有实际的 db 事务)没有看到回滚调用——因为它被调用一个孤立的块。有点奇怪。

解决方案 :
Klass.transaction(requires_new: true)

如果设置 requires_new,ActiveRecord 将使用或伪使用嵌套事务(对于 Postgres 它将创建嵌套事务,对于 MySQL/InnoDB 它将创建保存点)。当您使用 ActiveRecord 调用回滚时,它会确定其范围并发出正确的回滚。

另一种解决方案是使用截断或删除作为涉及事务的测试的策略。

关于ruby-on-rails - 自定义事务不适用于 rspec 中的 database_cleaner,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18143390/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com