ilrein
ilrein

Reputation: 3923

FactoryGirl Collections Not Carried Over

Here's my code snippet:

  context "(3) Integration" do

    let(:ad) { create(:ad) }
    let(:property) { create(:property, owner_id: 1) }
    let(:visitor_session) { create(:visitor_session, property_id: property.id) }
    let(:impression) { create(:impression, ad_id: ad.id, visitor_session_id: visitor_session.id) }

    # before(:each) do  
    #   DatabaseCleaner.clean_with(:truncation)
    # end

    describe "(a) An ad can check it's impressions" do 
      it do 
        expect(ad.impressions).to include impression 
      end
    end

    describe "(b) An ad can check the total impression count" do 
      it do
       expect(ad.impressions.count).to eq 1;
     end
   end
 end

The second test fails, when it really should be passing, and I'm quite flabbergasted. If I pass binding.pry in the middle of the first test, the output for ad.impressions returns a CollectionProxy:

#<ActiveRecord::Associations::CollectionProxy [#<Impression id: 1, start_at: "2014-12-05 17:17:40", duration: 10, is_valid: true, ad_id: 1, visitor_session_id: 1, created_at: "2014-12-05 17:17:49", updated_at: "2014-12-05 17:17:49">]>

Calling count on this, in the pry console, returns a value of 1.

When I get to the second test, ad appears to be the same object as in the first test, except now its impressions CollectionProxy is an empty array.

I suspected it might be a database cleaning issue, which is why I commented it out, but it didn't seem to have any effect. Here's my spec_helper for those needed more details:

require 'factory_girl'
require 'database_cleaner'
require 'devise'

RSpec.configure do |config|

  config.include Devise::TestHelpers, type: :controller
  config.include FactoryGirl::Syntax::Methods

  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
  config.color = true;

end

Why is my collection not persisting over to the second test?

Upvotes: 0

Views: 33

Answers (1)

infused
infused

Reputation: 24367

The only reason the first test passes is that you are calling impression directly within it, which cause the let(:impression) block to be evaluated - this creates the impression record the first time it is called.

Since the second test does not call impression at all, that record never gets created.

To fix it use let! which will evaluate the block before the test code itself:

let!(:impression) { create(:impression, ad_id: ad.id, visitor_session_id: visitor_session.id) }

See the let and let! documentation for more info.

Upvotes: 2

Related Questions