14

每当我运行用户测试时,RSpec 会在测试完成后将 Fabricated 用户留在测试数据库中,这会扰乱我的其他测试。我会做一个rake db:test:prepare,但是当我再次运行我的测试时,记录会在我的数据库中重新创建。我不知道为什么会这样。它只发生在用户对象上。

在我的 spec_helper 文件中,我什至有:

config.use_transactional_fixtures = true

这是一个创建记录的示例测试:

it "creates a password reset token for the user" do
  alice = Fabricate(:user) 
  post :create, email: alice.email
  expect(assigns(alice.password_reset_token)).to_not eq(nil)
end

制造商:

Fabricator(:user) do
  email { Faker::Internet.email }
  password 'password'
  name { Faker::Name.name }
end

这可能与我的用户模型有关吗?

4

4 回答 4

23

您应该使用一个名为 database_cleaner 的 gem,它将截断您的数据库并自动重置所有内容,因此在您的 gem 文件中添加 gem database_cleaner,然后在您的 spec_helper.rb 中配置它

spec_helper.rb

config.use_transactional_fixtures = false

config.before(:suite) do
  DatabaseCleaner.strategy = :truncation
end

config.before(:each) do
  DatabaseCleaner.start
end

config.after(:each) do
  DatabaseCleaner.clean
end

然后在您的规范/支持目录中创建一个新文件

规范/支持/shared_db_connection.rb

class ActiveRecord::Base
  mattr_accessor :shared_connection
  @@shared_connection = nil

  def self.connection
    @@shared_connection || retrieve_connection
  end
end
ActiveRecord::Base.shared_connection=ActiveRecord::Base.connection

现在,每当您运行测试时,数据库都会被重置。这取自 Aaron Sumner 的“使用 RSpec 进行日常 Rails 测试”一书

于 2013-10-06T15:58:30.937 回答
8

每个测试都包含在一个数据库事务中。这意味着当测试完成时,测试期间创建的所有内容都应该消失。因此,我怀疑您数据库中的任何内容都是在测试本身之外制作的(例如在一个before(:all)块中)。

此外,这并不能保证每次运行测试时数据库都是空的。您可能不小心以某种方式添加了一条记录,现在它只是不断恢复到该状态。

如果你想确保你的测试每次都有一个闪亮的数据库,你应该看看database_cleaner gem。

于 2013-10-06T15:51:49.427 回答
2

最简单的解决方案是确保 RSpec 测试在事务中运行(Rails 默认这样做)

spec_helper.rb

config.around(:each) do |example|
  ActiveRecord::Base.transaction do
    example.run
    raise ActiveRecord::Rollback
  end
end
于 2017-04-25T16:21:27.680 回答
0

如果我不得不猜测,这条线post :create, email: alice.email似乎很可能是进行实际用户创建的候选者。

用一个虚假的测试来存根,看看你是否仍然在数据库中创建一个用户。

于 2013-10-06T14:48:26.777 回答