Come si configurano le associazioni dei modelli in un test RSpec?
-
10-07-2019 - |
Domanda
Ho pastied le specifiche che ho scritto per i post / show.html.erb visualizza in un'applicazione che sto scrivendo come mezzo per imparare RSpec. Sto ancora imparando su beffe e mozziconi. Questa domanda è specifica per "dovrebbe elencare tutti i commenti relativi". spec.
Quello che voglio è testare che la vista spettacolo mostri i commenti di un post. Ma ciò di cui non sono sicuro è come impostare questo test e quindi fare in modo che l'iterazione del test con deve contenere istruzioni ('xyz'). Qualche suggerimento? Altri suggerimenti sono anche apprezzati! Grazie.
--- Modifica
Qualche informazione in più. Ho un named_scope applicato ai commenti a mio avviso (lo so, l'ho fatto un po 'indietro in questo caso), quindi @ post.comments.approved_is (true). Il codice pastied risponde con l'errore "non definito" metodo "approvato" per # ", il che ha senso da quando gli ho detto di stub commenti e di restituire un commento. Non sono ancora sicuro, tuttavia, come concatenare gli stub in modo che @ post.comments.approved_is (true) restituisca una serie di commenti.
Soluzione
Stubbing è davvero il modo di andare qui.
A mio avviso, tutti gli oggetti nel controller e le specifiche di visualizzazione devono essere testati con oggetti finti. Non è necessario dedicare del tempo a test ridondanti di logica che dovrebbe già essere accuratamente testata nelle specifiche del modello.
Ecco un esempio di come imposto le specifiche nel tuo Pastie & # 8230;
describe "posts/show.html.erb" do
before(:each) do
assigns[:post] = mock_post
assigns[:comment] = mock_comment
mock_post.stub!(:comments).and_return([mock_comment])
end
it "should display the title of the requested post" do
render "posts/show.html.erb"
response.should contain("This is my title")
end
# ...
protected
def mock_post
@mock_post ||= mock_model(Post, {
:title => "This is my title",
:body => "This is my body",
:comments => [mock_comment]
# etc...
})
end
def mock_comment
@mock_comment ||= mock_model(Comment)
end
def mock_new_comment
@mock_new_comment ||= mock_model(Comment, :null_object => true).as_new_record
end
end
Altri suggerimenti
Non sono sicuro che questa sia la soluzione migliore, ma sono riuscito a far passare le specifiche stubbing solo su named_scope. Gradirei qualsiasi feedback su questo, così come suggerimenti per una soluzione migliore, dato che ce n'è uno.
it "should list all related comments" do
@post.stub!(:approved_is).and_return([Factory(:comment, {:body => 'Comment #1', :post_id => @post.id}),
Factory(:comment, {:body => 'Comment #2', :post_id => @post.id})])
render "posts/show.html.erb"
response.should contain("Joe User says")
response.should contain("Comment #1")
response.should contain("Comment #2")
end
Sembra un po 'brutto.
Potresti fare qualcosa del tipo:
it "shows only approved comments" do
comments << (1..3).map { Factory.create(:comment, :approved => true) }
pending_comment = Factory.create(:comment, :approved => false)
comments << pending_comments
@post.approved.should_not include(pending_comment)
@post.approved.length.should == 3
end
O qualcosa in tal senso. Specificare il comportamento, alcuni metodi approvati dovrebbero restituire commenti approvati per un post. Potrebbe essere un metodo semplice o un named_scope. E in attesa farebbe anche qualcosa di ovvio.
Potresti anche avere una factory per: pending_comment, qualcosa come:
Factory.define :pending_comment, :parent => :comment do |p|
p.approved = false
end
Oppure, se il valore predefinito è false, puoi fare la stessa cosa per: approvato_commenti.
Mi piace molto l'approccio di Nick. Ho avuto lo stesso problema e sono stato in grado di fare quanto segue. Credo che funzionerebbe anche mock_model.
post = stub_model(Post)
assigns[:post] = post
post.stub!(:comments).and_return([stub_model(Comment)])