如何在RSpec测试中设置模型关联?

时间:2009-08-03 05:24:00

标签: model rspec associations

我已经pastied在我编写的应用程序中为posts / show.html.erb视图编写的规范,作为学习RSpec的一种方法。我还在学习嘲笑和顽固。此问题特定于“应列出所有相关注释”规范。

我想要的是测试节目视图显示帖子的评论。但我不确定的是如何设置此测试,然后让测试迭代,应该包含('xyz')语句。任何提示?其他建议也很感激!感谢。

---修改

更多信息。在我看来,我有一个named_scope应用于评论(我知道,在这种情况下我做了一些倒退),所以@ post.comments.approved_is(true)。代码贴出响应错误“未定义的方法`approved_is'为#”,这是有道理的,因为我告诉它存根注释并返回注释。但是,我仍然不确定如何链接存根以便@ post.comments.approved_is(true)将返回一组注释。

4 个答案:

答案 0 :(得分:4)

Stubbing真的是去这里的方式。

在我看来,控制器和视图规范中的所有对象都应该使用模拟对象进行存根。没有必要花时间冗余地测试已经在模型规范中进行过全面测试的逻辑。

以下是我如何在你的牧场中设置规格的例子......

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

答案 1 :(得分:1)

我不确定这是否是最佳解决方案,但我设法通过仅存在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")

答案 2 :(得分:0)

它看起来有点讨厌。

您可以执行以下操作:

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。

答案 3 :(得分:0)

我真的很喜欢尼克的做法。我自己也有同样的问题,我能够做到以下几点。我相信mock_model也可以。

post = stub_model(Post)
assigns[:post] = post
post.stub!(:comments).and_return([stub_model(Comment)])