Reputation: 3568
I'm using RSpec with FactoryGirl within a Ruby on Rails environment for testing.
I want to specify my factories as follows:
factory :user do
role # stub
factory :resident do
association :role, factory: :resident_role
end
factory :admin do
association :role, factory: :admin_role
end
end
And I'd like to do something like this in my spec:
require 'rails_helper'
RSpec.describe User, type: :model do
context "all users" do
# describe a user
# subject { build(:user) }
# it { is_expected.to be_something_or_do_something }
end
context "residents" do
# describe a resident
# subject { build(:resident) }
# it { is_expected.to be_something_or_do_something }
end
context "admins" do
# describe a admin
# subject { build(:admin) }
# it { is_expected.to be_something_or_do_something }
end
end
Can this be done by explicitly setting the subject
? When I do, I keep getting duplicate roles errors.
If anyone has any advice or suggestion, it would be greatly appreciated!
Upvotes: 3
Views: 1699
Reputation: 3568
I found the solution to my problems here: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations
What I needed to use in my user factories was association :role, factory: :role, strategy: :build
Upvotes: 0
Reputation: 3245
But this causes the user_spec.rb to use the :user factory.
No, it does not. Assuming you configured FactoryGirl correctly, RSpec can use whatever factory you'd like "on demand" in any test file. Configuration-wise, in rails_helper.rb
throw this in:
RSpec.configure do |config|
# ...
config.include FactoryGirl::Syntax::Methods
# ...
end
Then, in your spec file:
require 'rails_helper'
RSpec.describe User, type: :model do
context "all users" do
let(:user) { create(:user) }
it 'is a user' do
# Here `user` is going to be a user factory
expect(user.unit).not_to be_present
end
end
context "residents" do
let(:user) { create(:resident) }
it 'is a resident' do
# Here `user` is going to be a resident factory
expect(user.unit).to be_present
end
end
context "admins" do
let(:user) { create(:admin) }
it 'is an admin' do
# Here `user` is going to be an admin factory
expect(user.role).to be('admin_role')
end
end
end
In short, you can use create(<factory_name>)
on any factory definition that exists in any one of these paths:
test/factories.rb
spec/factories.rb
test/factories/*.rb
spec/factories/*.rb
Note that if you haven't placed the config.include FactoryGirl::Syntax::Methods
inside your RSpec.configure
, you can still create any factory, by doing FactoryGirl.create(<factory_name>)
instead of create(<factory_name>)
.
Upvotes: 3
Reputation: 487
I don't think you would want to stop them from auto loading, and I'm not actually sure what your use case is for not allowing them to load?
RSpec automagically fetches the factory for a spec
Rspec loads all the factories into memory when your spec helper loads I believe. Because your using factory inheritence your just loading each of these into memory before your tests run, nothing is being called, no objects are being created or built. They are just ready to use in your tests.
Are you getting a specific error or is there some case I'm not seeing that you need?
Upvotes: 0