factory_girl + rspec doesn't seem to roll back changes after each example
Asked Answered
W

7

18

Similar to the problem described here: http://rpheath.com/posts/411-how-to-use-factory-girl-with-rspec

in Short (shorten'd code):

spec_helper:

config.use_transactional_fixtures = true
config.use_instantiated_fixtures  = false

factories.rb:

Factory.define :state do
  f.name "NY"
end

in my spec

before(:each) do 
  @static_model = Factory(:state) # with validate uniqueness of state name
end

error:

duplicate entry name "NY" etc.


Question: Shouldn't rspec clear database before each spec example and hence not throwing duplicate entry errors?

Wizardly answered 26/7, 2010 at 9:49 Comment(0)
D
42

Things i think off:

  • do you use rake spec to run your testsuite: that builds up the database from scratch (to make sure nothing is sticking)
  • do you use, anywhere, a before (:all) ? Because whatever you create inside a before :all should be deleted again in a after :all or it keeps on existing.
Dap answered 26/7, 2010 at 14:38 Comment(1)
To reiterate nathanvda's suggestion, since I don't have enough karma to vote his post up: Make sure that all before(:all) blocks that insert DB records have a corresponding after(:all) block to destroy them!Skell
P
3

Question: Shouldn't rspec clear database before each spec example and hence not throwing duplicate entry errors?

RSpec with DatabaseCleaner or RSpec Rails with use_transactional_fixtures will clear the DB as long as your created the data in the example itself. before :all do ... end is considered outside of the example, because the data remains untouched across multiple examples. Whatever you create in before :all you have to delete in after :all.

In order to delete whatever you create automatically use before :each do ... end. Be aware the same data will be created and removed 10 times if you have 10 examples. The difference between before :all and before :each is better explained here: rails rspec before all vs before each

Penumbra answered 23/6, 2014 at 18:22 Comment(0)
R
2

Some more possible causes:

  • There's still a states.yml fixture sitting around
  • Someone played around on script/console test and forgot to clean up afterwards.
Revolution answered 1/8, 2010 at 15:19 Comment(0)
S
2

You might also find it's because you haven't wrapped the statement in:

describe "what it should do" do
  @static_model = Factory(:state) # with validate uniqueness of state name
end

I discovered that was the change that solved this problem: Why isn't factory_girl operating transactionally for me? - rows remain in database after tests

Scend answered 17/8, 2010 at 3:57 Comment(1)
Thats wrong. If you create the record out of a before(:each) or before(:all) block, you will create the record at the time the test suite is loaded, not when it's executed. Sure you will have the record created only once, but that was by chance. Take care of this if you don't want to end up with frustrating understandable code.Sturgis
S
1

I have had similar questions about what sort of starting state one can expect when using FG and RSpec.

While I too wait for clarity, Database Cleaner could be a good fix: http://rubydoc.info/gems/database_cleaner/0.6.7/frames hth - Perry

Staple answered 29/4, 2011 at 17:6 Comment(0)
D
0

When you use Factory(:state) wich is a shortcut to Factory.create(:state), factory_girl returns you a saved object.

Use Factory.build(:state) instead.

Dillondillow answered 3/10, 2011 at 2:5 Comment(0)
A
0

Dude maybe your yaml fixtures from regular unit tests get mixed into your rspec?

Amygdaline answered 27/10, 2011 at 1:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.