Como faço para associações modelo de configuração em um teste RSpec?
-
10-07-2019 - |
Pergunta
pastied as especificações que eu escrevi para a vista posts / show.html.erb em um aplicativo que eu estou escrevendo como um meio para aprender RSpec. Eu ainda estou aprendendo sobre simulações e stubbing. Esta questão é específico para o "deve listar todos os comentários relacionados" spec.
O que eu quero é prova de que a visão show exibe os comentários de um post. Mas o que eu não estou certo sobre é como configurar este teste e, em seguida, fazer o teste iterate através com deve conter declarações ( 'xyz'). Alguma dica? Outras sugestões também são apreciados! Obrigado.
--- Editar
Alguns mais informações. Eu tenho um named_scope aplicado aos comentários na minha opinião (eu sei, eu fiz isso um pouco para trás, neste caso), então @ post.comments.approved_is (verdadeiro). O código pastied responde com o erro "undefined method` approved_is' para #", o que faz sentido desde que eu disse a ele esboço comentários e retornar um comentário. Eu ainda não tenho certeza, no entanto, como a cadeia os topos de modo que post.comments.approved_is @ (true) irá retornar uma matriz de comentários.
Solução
Stubbing é realmente o caminho a percorrer aqui.
Na minha opinião, todos os objetos em especificações do controlador e vista deve ser arrancado com objetos fictícios. Não há nenhuma necessidade real para passar o tempo de forma redundante testar lógica que já deve ser testado exaustivamente em suas especificações modelo.
Aqui está um exemplo de como eu iria configurar as especificações em seu Pastie ...
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
Outras dicas
Eu não tenho certeza se esta é a melhor solução, mas eu consegui obter a especificação de passar por arrancar apenas o named_scope. Eu apreciaria qualquer comentário sobre este, bem como sugestões para uma melhor solução, uma vez que há um.
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")
final
Ele lê um pouco desagradável.
Você poderia fazer algo como:
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
Ou algo nesse sentido. Especificação do comportamento, algum método aprovado deve retornar comentários para um post aprovado. Isso poderia ser um método simples ou um named_scope. E pendentes faria algo óbvio assim.
Você também pode ter uma fábrica para: pending_comment, algo como:
Factory.define :pending_comment, :parent => :comment do |p|
p.approved = false
end
Ou, se falsa é o padrão, você poderia fazer a mesma coisa para:. Approved_comments
Eu realmente gosto de abordagem de Nick. Eu tive o mesmo problema mim e eu era capaz de fazer o seguinte. Acredito mock_model iria funcionar tão bem.
post = stub_model(Post)
assigns[:post] = post
post.stub!(:comments).and_return([stub_model(Comment)])