Iggy
Iggy

Reputation: 5251

How to use factorygirl to associate user_id

I am learning to do tests using Rails testing tools, mainly: rspec, factory_girl, shoulda, and faker gems.

I want to test has_one and belongs_to associations. I have user.rb (with name) and address.rb (with street, city, and user_id) models.

I am trying to figure out how to create fake associations using fakers. I want to create a fake street and associate it with a fake user, but I can't figure out how to do it on spec/factories/addresses.rb

This is what I currently have:

FactoryGirl.define do
  factory :address do
    street    {Faker::Address.street_address}
    city      {Faker::Address.city}
    #Creates fake user and use that user's id for user_id)#
    user = build(:user, name: "Joe", id: 2)
    user_id   {user.id}
  end
end

This is the spec/models/address_spec.rb

require 'rails_helper'

RSpec.describe Address, type: :model do
  it "has a valid factory" do
    address = build(:address)
    expect(address).to be_valid
  end
  it {should belong_to(:user)}
end

When I run it, it shows add_attribute': wrong number of arguments (given 3, expected 1..2) (ArgumentError) error. I tried removing the id on the argument and just did user = build(:user, name: "Joe") but the same error message still shows.

The test passes if I don't include the user lines on addresses factory. I confirmed that address has belongs_to :user and user has has_one :address.

Is it possible to generate fake association and associate address to a fake user.id? I would like to test Address's user_id as well.

Edit - following are the related factories and models:

Factories

addresses.rb

FactoryGirl.define do
  factory :address do
    street    {Faker::Address.street_address}
    city      {Faker::Address.city}
    user
  end
end

users.rb

FactoryGirl.define do
  factory :user do
    name      {Faker::Name.name}
  end
end

spec/models

address_spec.rb

require 'rails_helper'

RSpec.describe Address, type: :model do
  it "has a valid factory" do
    association user
    specific_user = build(:user, name: 'Joe')
    address = build(:address, specific_user)
    expect(address).to be_valid
  end
  it {should belong_to(:user)}
end

Error running address_spec.rb

 NameError:
   undefined local variable or method `user' for #<RSpec::ExampleGroups::Address:0x00000001a94b00>
 # ./spec/models/addres

Upvotes: 1

Views: 1293

Answers (1)

kasperite
kasperite

Reputation: 2478

I think the way you build association is incorrect. See https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations.

If you want a more specific associated user eg name: Joe, id: 2, it's probably better to do it in spec.

Factory:

FactoryGirl.define do
  factory :address do
    street    {Faker::Address.street_address}
    city      {Faker::Address.city}
    user
  end
end

Spec:

 it "has a valid factory" do
    specific_user = build(:user, name: 'Joe')
    address = build(:address, specific_user)
    expect(address).to be_valid
 end

Upvotes: 2

Related Questions