RSpecテストでモデルの関連付けを設定するにはどうすればよいですか?
-
10-07-2019 - |
質問
貼り付け、posts / show.html.erbビューで記述した仕様をRSpecを学ぶための手段として私が書いているアプリケーション。私はまだモックとスタブについて学んでいます。この質問は、「関連するすべてのコメントをリストする必要があります」に固有のものです。スペック
私が望むのは、ショービューに投稿のコメントが表示されることをテストすることです。しかし、私はこのテストをどのように設定し、テストを含む必要があります( 'xyz')ステートメントを使用して反復するかについてはわかりません。ヒントはありますか?他の提案も歓迎します!ありがとう。
---編集
詳細情報。ビューのコメントにnamed_scopeを適用しているので(この場合は少し逆にした)、@ post.comments.approved_is(true)です。貼り付けられたコードは、エラー「" undefined method `approved_is 'for#"」で応答します。これは、スタブコメントを伝えてコメントを返すので意味があります。ただし、@ post.comments.approved_is(true)がコメントの配列を返すようにスタブをチェーンする方法はまだわかりません。
解決
スタブは本当にここに行く方法です。
私の意見では、コントローラーおよびビューの仕様内のすべてのオブジェクトは、モックオブジェクトでスタブ化する必要があります。モデルの仕様で既に徹底的にテストされているロジックを冗長にテストするために時間を費やす必要はありません。
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
他のヒント
これが最善の解決策であるかどうかはわかりませんが、named_scopeだけをスタブすることで仕様を通過させることができました。これについてのフィードバックと、より良い解決策があればそれに対する提案をいただければ幸いです。
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")
終了
少々厄介です。
次のようなことができます:
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
またはその効果のための何か。動作を指定し、承認されたいくつかのメソッドは、投稿に対して承認されたコメントを返す必要があります。これは、プレーンメソッドまたはnamed_scopeの場合があります。また、保留中は明らかなことも行います。
:pending_commentのファクトリもあります。次のようなものです。
Factory.define :pending_comment, :parent => :comment do |p|
p.approved = false
end
または、falseがデフォルトの場合、:approved_commentsに対して同じことを行うことができます。
私はニックのアプローチが本当に好きです。私自身も同じ問題を抱えており、次のことができました。 mock_modelも同様に機能すると思います。
post = stub_model(Post)
assigns[:post] = post
post.stub!(:comments).and_return([stub_model(Comment)])