Rspec/FactoryGirl: clean database state

自作多情 提交于 2019-12-09 02:28:04

问题


I am new to Rspec and Factory girl and would like my test to run on a specific database state. I understand I can get Factory girl to create these records, and the objects will be destroyed after the test run, but what happens if I have data in the database.

For example: I want my test to run when there are 3 records in the database that I created through Factory Girl. However, I currently already have 1 model record in the database, and I don't want to delete it just for the test. Having that 1 model in there ruins my test.

Database Content

[#<Leaderboard id: 1, score: 500, name: "Trudy">]

leaderboard_spec.rb

require 'spec_helper'

describe Rom::Leaderboard do

    describe "poll leaderboard" do
        it "should say 'Successful Run' when it returns" do
            FactoryGirl.create(:leaderboard, score: 400, name: "Alice")
            FactoryGirl.create(:leaderboard, score: 300, name: "Bob")
            FactoryGirl.create(:leaderboard, score: 200, name: "John")
            Leaderboard.highest_scorer.name.should == "Alice"
        end
    end

end

Now my test will fail because it will incorrectly assume that Trudy is the highest scorer, since the test have run in an incorrect state.

Does factory girl offer anyway to delete records from the database then rollback this delete? Similar to how it creates records in the database and rollsback


回答1:


Its popular to use the database_cleaner gem. You can find it here:

https://github.com/bmabey/database_cleaner

The documentation recommends the following configuration for rspec:

RSpec.configure do |config|

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

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

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

end

This will you make sure you have a clean database for each test.




回答2:


To answer your rollback question as directly as possible: no there isn't a way to rollback a delete within a test.

Following test conventions your goal usually is to start with a clean slate, and use factory_girl to efficiently build the scenario in the database you need to test for.

You can accomplish what you want by, for instance, adding a this to your leaderboards.rb factory file:

factory :trudy do
  id 1
  score 500
  name "Trudy"
end

Or you could create a simple helper function in your test file that regenerates that record when its needed for tests:

def create_trudy
  FactoryGirl.create :leaderboard,
    id: 1,
    score: 500,
    name: "Trudy"
  end
end

Or you could place all this in a before(:suite) within a describe block, like so:

describe "with a leaderboard record existing" do
  before(:each) do
    FactoryGirl.create :leaderboard, id: 1, score: 500, name: "Trudy"
  end
  # Tests with an initial leaderboard record
end
describe "with no leaderboard records initially" do
  # Your test above would go here
end

In this final suggestion, your tests become very descriptive and when viewing the output, you will know exactly what state your database was in at the beginning of each test.



来源:https://stackoverflow.com/questions/21323239/rspec-factorygirl-clean-database-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!