Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec leaves record in test database

Whenever I run a user test, RSpec leaves the Fabricated user in the test database after the test has completed, which is messing up my other tests. I will do a rake db:test:prepare, but when I run my tests again, the record is recreated in my database. I have no idea why this is happening. It only happens with user objects.

In my spec_helper file I even have:

config.use_transactional_fixtures = true

Here is an example test that creates a record:

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:

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

Could this have anything to do with my users model?

like image 974
DMiller Avatar asked Oct 06 '13 14:10

DMiller


3 Answers

Each test is wrapped in a database transaction. That means that everything created during the test should be gone when the test finishes. Therefore, I would suspect that whatever you have in your database was made outside the test itself (like in a before(:all) block).

Also this doesn't guarantee that your database will be empty each time you run your tests. It might be possible that you accidentally added a record somehow, and now it just keeps reverting to that state.

If you want to make sure your tests have a shiny database each time, you should have a look at the database_cleaner gem.

like image 76
iain Avatar answered Oct 22 '22 23:10

iain


you should use a gem called database_cleaner that will truncate your database and reset everything automatically so in your gem file add the gem database_cleaner after that inside your spec_helper.rb configure it

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

and then create a new file in your spec/support directory

spec/support/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

Now whenever you run your tests the database will be reset.This was taken from the book 'Everyday Rails testing with RSpec' by Aaron Sumner

like image 41
Brock90 Avatar answered Oct 22 '22 22:10

Brock90


The simplest solution is to make sure RSpec tests run in transactions (Rails does this by default)

spec_helper.rb

config.around(:each) do |example|
  ActiveRecord::Base.transaction do
    example.run
    raise ActiveRecord::Rollback
  end
end
like image 2
Yossi Shasho Avatar answered Oct 22 '22 23:10

Yossi Shasho