Search code examples
ruby-on-railsrspecruby-on-rails-5rspec-rails

Rspec Model Association Test not working on model subclass


class Proofreader < Role

  has_many :proofreading_jobs,   :class_name => 'ProofreadingJob',   :foreign_key => 'proofreader_id'

end

class ProofreadingJob < ApplicationRecord

  belongs_to :proofreader, class_name: 'Role', foreign_key: :proofreader_id, optional: true
  belongs_to :client,      class_name: 'Role', foreign_key: :client_id
  end

class Role < ApplicationRecord

  belongs_to :user

end

proofreaders factory:

    FactoryBot.define do
      factory :proofreader do
        type { 'Proofreader'}
        hourly_rate { 15 }
        association :user, factory: :employee_user

        factory :proofreader_with_work_events do

          after :create do |proofreader|
            create(:user_event, :recurring_mwf, user: proofreader.user)
          end

        end
      end
    end

spec/model_roles/proofreader_spec.rb

RSpec.describe 'Proofreader', type: :model do

  describe "Associations" do
    it { should have_many(:proofreading_jobs) }
  end

end

Test fails with:

Failure/Error: it { should have_many(:proofreading_jobs) }
       expected Associations to respond to `has_many?`

Clearly the class ProofreadingJob has the association there. How can I write this test so it passes?


Solution

  • First of all, you have to define a subject - the object your tests will interact with.

    It can be something like this:

    describe "Associations" do
      expect(ProofreadingJob.new).to be_valid # ProofreadingJob.new is subject here
    end
    

    When you got the understanding of subject you can test the association. It can be like this:

    RSpec.describe ProofreadingJob, type: :model do
      it { should have_many(:proofreading_jobs) }
    end
    

    Here's the subject is defined by Rspec from ProofreadingJob, type: :model line. Please note that ProofreadingJob is not a string but actual model name (class), so Rspec will know how to make subject from that model.

    To use such syntax you have to add shoulda-matchers