14

How do you delete the objects (in the database and in the memory) you created

  • after each test
  • AND after each context? (in a context it could make sense to build tests on each other)

Is there a method to do this automatically?

I have the following problem:

Each test saves entries to the database. The next test then depends on these entries. Even if I wanted to build tests that are dependent on other tests, I couldn't, because the order in which the tests get executed is not controllable.

factories.rb:

sequence(:name) { |n| "purchaser #{n}" }      

organization_spec.rb:

context "when no supplier exists" do
  it "finds no associated suppliers" do
    purchaser = create(:organization_purchaser)                
    purchaser.partners.empty?.should == true
  end
end

context "when one supplier exists" do
  it "finds one associated suppliers" do
    purchaser = create(:organization_purchaser)      
    supplier = create(:organization_supplier)
    partnership = create(:partnership, organization: purchaser, partner: supplier)         
    purchaser.partners.last.name.should == "purchaser 1"
  end
end

context "when two suppliers exist" do        
  it "finds two associated suppliers" do
    purchaser = create(:organization_purchaser)      
    2.times do |i|
      supplier = create(:organization_supplier)
      partnership = create(:partnership, organization: purchaser, partner: supplier) 
    end    
    purchaser.partners.last.name.should == "purchaser 2"
  end
end

RSpec output:

Organization
  #suppliers_for_purchaser
    responds
    when no supplier exists
      finds no associated suppliers
    when two suppliers exist
      finds two associated suppliers
    when one supplier exists
      finds one associated suppliers (FAILED - 1)

Failures:

1) Organization#suppliers_for_purchaser when one supplier exists finds one associated suppliers
 Failure/Error: purchaser.partners.last.name.should == "purchaser 1"
   expected: "purchaser 1"
        got: "purchaser 3" (using ==)
migu
  • 4,236
  • 5
  • 39
  • 60

3 Answers3

16

You should use Database Cleaner

All you have to do is add the following code to your Rspec configuration file spec_helper.rb

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

UPDATE

As of Rails 5.1 this is not needed if you use config.use_transactional_tests

https://github.com/rails/rails/pull/19282

Leo Correa
  • 19,131
  • 2
  • 53
  • 71
8

Did you try adding a before method ?

describe MyController do

before(:each) do
  User.delete_all
  MyOtherModel.delete_all
  ...
end
aherve
  • 3,795
  • 6
  • 28
  • 41
1

I think your question is more along the lines of how can I reset a factory girl sequence? Those arent stored in the database, even if you delete all you will still have the issue. When testing something like this I find it easer to just override the factory girl sequence..

it "finds one associated suppliers" do
    purchaser = create(:organization_purchaser)      
    supplier = create(:organization_supplier , name: "My First Supplier")
    partnership = create(:partnership, organization: purchaser, partner: supplier)         
    purchaser.partners.last.name.should == "My First Supplier"
  end

The other things you probably do is something like

it "finds one associated suppliers" do
        purchaser = create(:organization_purchaser)      
        supplier = create(:organization_supplier)
        partnership = create(:partnership, organization: purchaser, partner: supplier)         
        purchaser.partners.last.should == supplier 
      end

or even

it "finds one associated suppliers" do
        purchaser = create(:organization_purchaser)      
        supplier = create(:organization_supplier)
        partnership = create(:partnership, organization: purchaser, partner: supplier)         
        purchaser.partners.last.name.should == supplier.name
      end
Doon
  • 19,719
  • 3
  • 40
  • 44