事务
当你运行`rails generate rspec:install`时,`spec/rails_helper.rb` 文件包含以下配置
RSpec.configure do |config|
config.use_transactional_fixtures = true
end
这个设置的名称有点误导人。它在 Rails 中的真正含义是“在事务中运行每个测试方法”。在 rspec-rails 的上下文中,它意味着“在事务中运行每个示例”。
想法是,每个示例都从一个干净的数据库开始,创建该示例所需的任何数据,然后在示例结束时通过简单地回滚事务来删除这些数据。
禁用事务
如果你更喜欢自己管理数据,或者使用其他工具(如database_cleaner)来为你管理数据,只需告诉 RSpec 告诉 Rails 不要管理事务
RSpec.configure do |config|
config.use_transactional_fixtures = false
end
在`before(:example)`中创建的数据将被回滚
你在`before(:example)`钩子中创建的任何数据都将在示例结束时被回滚。这是一件好事,因为它意味着每个示例都与其他示例留下的状态隔离开来。例如
describe Widget do
before(:example) do
@widget = Widget.create
end
it "does something" do
expect(@widget).to do_something
end
it "does something else" do
expect(@widget).to do_something_else
end
end
上面的两个示例中都重新创建了`@widget`,因此每个示例都有一个不同的对象,并且底层数据被回滚,因此每个示例中`@widget`支持的数据都是新的。
在`before(:context)`中创建的数据不会被回滚
`before(:context)`钩子在事务打开之前被调用。你可以用它来加速,在组中的任何示例运行之前创建一次数据,但是,这会带来一些复杂性,你应该只在完全理解其含义的情况下这样做。以下是一些准则
确保在`after(:context)`钩子中清理所有数据
before(:context) do @widget = Widget.create! end after(:context) do @widget.destroy end
如果你不这样做,你就会留下一些数据,这些数据最终会干扰其他示例。
在`before(:example)`钩子中重新加载对象。
before(:context) do @widget = Widget.create! end before(:example) do @widget.reload end
即使每个示例中的数据库更新将被回滚,但对象不会知道这些回滚,因此对象及其支持的数据很容易不同步。