Rspec - How to clean the database after each test
Asked Answered
H

5

9

I have a feature spec with Capybara for a login page, and I am using FactoryGirl + DatabaseCleaner

require 'rails_helper'

feature 'Admin signs in' do

  background do
    FactoryGirl.create(:user)
  end

  scenario 'with valid credentials' do
    visit admin_root_path
    fill_in 'user_email', :with => '[email protected]'
    fill_in 'user_password', :with => 'testpassword'
    click_button 'Sign in'
    expect(page).to have_content('Dashboard')
  end

  scenario 'with invalid credentials' do
    visit admin_root_path
    fill_in 'user_email', :with => '[email protected]'
    fill_in 'user_password', :with => 'wrongpassword'
    click_button 'Sign in'
    expect(page).to have_content('Admin Login')
  end

end

running the test, I get the following error:

1) Admin signs in test with invalid credentials
 Failure/Error: FactoryGirl.create(:user)
 ActiveRecord::RecordInvalid:
   Validation failed: Email has already been taken

I thought DatabaseCleaner would revert the changes, but it looks like the user record persist in the database till the second scenario block.

How can I make sure that the database is cleaned after the first scenario?

I configured Database cleaner following this post

# support/database_cleaner_spec.rb

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  end

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

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

end

I have also updated the spec helper file with:

config.use_transactional_fixtures = false
Halflight answered 6/4, 2015 at 7:3 Comment(0)
H
11

I was wrongly assuming that configuration files in spec/support folder were automatically loaded, but it turns out that I had to uncomment the following line in spec/rails_helper.rb

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

The DatabaseCleaner config file was correct, it just wasn't loaded at all.

Halflight answered 6/4, 2015 at 16:58 Comment(0)
F
9

Make sure you have the following configuration in spec/rails_helper.rb

RSpec.configure do |config|
 config.use_transactional_fixtures = true
end

The idea is to start each example with a clean database, create whatever data is necessary for that example, and then remove that data by simply rolling back the transaction at the end of the example.

Fatherly answered 6/4, 2015 at 8:16 Comment(0)
D
0

use these settings:

config.before(:suite) do
  DatabaseCleaner.clean_with(:truncation)
end
Dignitary answered 6/4, 2015 at 7:49 Comment(1)
I have already that settings, I've updated my question with the DatabaseCleaner config file. The Database cleaner actually works fine, except for "after(:each)"Halflight
A
0

If by any chance you are using MySQL and altering tables (reset auto increments or whatever DDL operation) within a method within a test, the transaction strategy will fail and your database will not be cleaned.

In order to fix, you have to declare a config block like this:

config.before(:each, :altering_database => true) do
  DatabaseCleaner.strategy = :truncation
end

And add this config to your test context:

context "when you alter the DB", :altering_database => true do...

Note: this will slow down your tests, so be careful not to abuse it.

Anemology answered 13/10, 2016 at 15:34 Comment(0)
L
0
  config.before(:example) do
    DatabaseCleaner.clean_with(:truncation)
  end

worked for me!

Liminal answered 5/7, 2017 at 13:29 Comment(1)
Actually, mine used :example, which none of the other answers did...before(:suite) cleans the DB after each individual test, which I believe is what the user needed.Liminal

© 2022 - 2024 — McMap. All rights reserved.