2017-09-21 3 views
0

j'ai un a beaucoup à travers le modèle de relation comme ceci:RSpec has_many à # <ActiveRecord :: Associations :: CollectionProxy>

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 

Je dois créer un médecin qui a de nombreux patients, non? ainsi de suite mon test:

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

et je l'ai fait:

before { physician.patients << patients } 

Je veux tester le JSON généré avec ce

expect(physician.as_json).to eq({ 
    "id" => physician.id, 
    "name" => physician.name, 
    "patients" => physician.patients 
}) 

Je m'y attendais passerait mais il a échoué à cause de cela #<ActiveRecord::Associations::CollectionProxy>

J'ai vérifié en utilisant binding.pry par ceci:

physician.patients == patients et le résultat a été true

Pourriez-vous me aider, que je manque quelque chose ici?

+2

'médecin.patients' est une collection d'enregistrements. Ce n'est pas égal aux ** données json attendues **. Il y a plusieurs façons d'écrire ceci, mais fondamentalement votre test est faux - vous devez d'une manière ou d'une autre définir le ** format json ** que le résultat attendu devrait être. –

+1

'# as_json' malgré le nom retourne un hash sérialisable - pas JSON. Sinon votre commentaire est sur @TomLord – max

+0

merci @TomLord J'ai pu résoudre mon cas avec tous vos commentaires. – nrmb

Répondre

1

Pour créer un lien médecin et les patients passent juste la clé de create_list:

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

Ou vous pouvez le déclarer comme:

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

Mais le test lui-même est encore cassé comme mentionné par @TomLord . Vous avez besoin de tester le hachage - comme incluant une association le fera être converti en un hachage sérialisé:

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

Test de la sortie exacte eq n'est pas optimale car chaque modification de la sérialisation briser le test. Au lieu de cela, vous pouvez utiliser le include matcher pour indiquer ce qui doit être présent:

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 

Sauf si vous avez remplacé la méthode as_json cette spécification devrait échouer car vous devez inclure explicitement les associations avec physician.as_json(include: :patients).

+0

Surcharger as_json n'est pas une très bonne solution en premier lieu - vous pourriez vouloir repenser l'approche générale. https://robots.thoughtbot.com/better-serialization-less-as-json – max