Factorybot created Instance not existing until I reference it

43 Views Asked by At

I am writing tests in Rspec with Factorybot.

When my test looks like this, it fails:

describe "The #add_admin function" do
    context "with a normal user" do
      let(:user) { create(:user) }
      let(:role) { create(:admin_role) }

      it "adds the admin role" do
       
        expect(user.roles.map(&:name)).not_to include "admin"
        user.make_admin
        expect(user.roles.map(&:name)).to include "admin"
      end
    end
  end
end

with the error stating

 ActiveRecord::AssociationTypeMismatch:
       Role(#13660) expected, got nil which is an instance of NilClass(#40)

Which says to me that the role doesn't exist yet

but like this, without changing anything, it passes:

describe "The #add_admin function" do
    context "with a normal user" do
      let(:user) { create(:user) }
      let(:role) { create(:admin_role) }

      it "adds the admin role" do
        role
        expect(user.roles.map(&:name)).not_to include "admin"
        user.make_admin
        expect(user.roles.map(&:name)).to include "admin"
      end
    end
  end
end

Something like this makes me think I may be approaching the test wrong... The function that I'm testing looks like this:

class User < ApplicationRecord
    has_many :user_roles, dependent: :destroy
    has_many :roles, through: :user_roles
    ...
    def make_admin
        admin_role = Role.find_by(name: :admin)
        roles << admin_role
    end
end

My factories look like this:

users.rb

FactoryBot.define do
  factory :user do
    first_name { 'Joe' }
    last_name  { 'Schmo' }
    email { Faker::Internet.email }
    roles { [] }
    trait :with_role do
      transient do
        role { nil }
      end 
      roles { [association(:role, name:role)] }
    end
    
    trait :admin_user do
      roles { [association(:admin_role)] }
    end
  end
end

roles.rb

FactoryBot.define do
  factory :role do
    name { Faker::Job}
  end
  
  factory :admin_role, class: Role do 
    name { "admin" }
  end
end

I have seen this error/bug before on a different code base but I was working on legacy code and the idea was "do what works". Now im starting from scratch on a project and would like to eliminate the problem when its small.

0

There are 0 best solutions below