RSpec has_many通过#<activerecord :: associations :: collectionproxy>

时间:2017-09-21 11:07:02

标签: ruby-on-rails ruby activerecord rspec associations

我有很多这样的关系模型:

class Physician < ApplicationRecord
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ApplicationRecord
  belongs_to :physician
  belongs_to :patient
end

class Patient < ApplicationRecord
  has_many :appointments
  has_many :physicians, through: :appointments
end

我需要创建一位有很多患者的医生,对吧? 所以我的测试:

let!(:physician) { create(:physician) }
let!(:patients) { create_list(:patients, 2) }

我这样做了:

before { physician.patients << patients }

我想用这个

来测试生成的json
expect(physician.as_json).to eq({
  "id" => physician.id,
  "name" => physician.name,
  "patients" => physician.patients
})

我希望它会通过,但由于#<ActiveRecord::Associations::CollectionProxy>

而失败了

我使用binding.pry进行了检查:

physician.patients == patients 结果是true

你介意帮助我,我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:1)

要将医生和患者联系起来,只需将密钥传递给create_list

let!(:patients) { create_list(:patients, 2, physician: physician ) }

或者您可以将其声明为:

let(:physician) { create(:physician, patients: build_list(patients: 2)) }

但@TomLord提到的测试本身仍然存在问题。您需要测试生成的哈希 - 因为包括关联将导致它转换为序列化哈希:

{
  "id" => 1,
  "name" => "Dr Suess",
  "patients" => [
     {
        "id" => 1,
        "name" => "The Cat in The Hat"
     },
     {
        "id" => 2,
        "name" => "The Grinch"
     },
  ]
}

使用eq测试确切的输出并不是最佳的,因为序列化的每次更改都会破坏测试。相反,您可以使用include matcher来指定必须存在的内容:

describe '#as_json' do
   let!(:physician) { create(:physician) }
   let!(:patients) { create_list(:patients, 2) }
   subject(:serialized) { physician.as_json } 

   it { should include({
        "id" => physician.id,
        "name" => physician.name
   }) }
   it "includes the patients" do
      expect(serialized["patients"].length).to eq patients.length
      expect(serialized["patients"]).to include patients.first.as_json
      expect(serialized["patients"]).to include patients.last.as_json
   end
end

除非您已覆盖as_json方法,否则此规范应失败,因为您需要明确包含与physician.as_json(include: :patients)的关联。