msmith1114
msmith1114

Reputation: 3231

Rails FactoryBot/Rspec not creating using let

So this is my first time writing unit tests, and Im incorporating Rspec w/FactoryBot.

My Specs were working just fine with using @ instance variables, However when I use let! the second model fails because the first model was never created.

Spec:

require "rails_helper"

RSpec.describe Note, :type => :model do

  before(:all) do
    let!(:event){ FactoryBot.create(:event) }
    let!(:note){ FactoryBot.create(:note) }
  end

  it "is valid with valid attributes" do
    expect(note).to be_valid
  end

end

Factories:

FactoryBot.define do
  factory :note do
    event_id Event.first.id
    content "This is a sample note"
  end
end


FactoryBot.define do
  factory :event do
    title "Event Factory Test"
    event_date Date.today
    event_time "1:30 PM"
  end
end

As you can see, the note requires a Event id (Which requires the event to be created), but it complains when trying to find Event.first.id which should have been created from the let!).

Any ideas? This "seems" to be similar to how others use let in other rspec tests.

Upvotes: 2

Views: 4704

Answers (1)

max
max

Reputation: 102368

let and let! do not work if you wrap them in a before block.

require "rails_helper"
RSpec.describe Note, :type => :model do
  let!(:event){ FactoryBot.create(:event) }
  let!(:note){ FactoryBot.create(:note) }
  it "is valid with valid attributes" do
    expect(note).to be_valid
  end
end

Also to setup an association within a factory simply pass the name of the factory:

FactoryBot.define do
  factory :note do
    event # short for association :event
    content "This is a sample note"
  end
end

(If the factory name is the same as the association name, the factory name can be left out.).

You're still thinking about factories wrong though. They should be factories that produce unique testable records. Not a set of fixtures. The way you have defined it the factory would only work if a event has been created. Never hardwire factories!

If you want to get the event later just do:

require "rails_helper"
RSpec.describe Note, :type => :model do
  let!(:note){ FactoryBot.create(:note) }
  it "has an event" do
    expect(note.event).to be_a Event
  end
end

Upvotes: 3

Related Questions