我正在尝试为我的控制器解决我的RSpec测试,但它不起作用,我需要一些帮助来搞清楚。
我的Rspec是:
before(:each) do
@topic = mock_model(Topic, :update_attributes => true)
Topic.stub!(:where).with({:slug=>"some-slug"}).and_return(@topic)
with_valid_user
end
it "should find topic and return object" do
Topic.should_receive(:where).with("some-slug").and_return(@topic)
put :update, :topic_slug => "some-slug", :topic => {}
end
我想测试的控制器逻辑是:
def get_topic
@topic = Topic.where(:slug => params[:topic_slug]).first
@topic
end
但我得到的输出是:
Failure/Error: Topic.stub!(:where).with({:slug=>"some-slug"}).first.and_return(@topic)
NoMethodError:
undefined method `first' for #<RSpec::Mocks::MessageExpectation:0x104c99910>
# ./spec/controllers/topics_controller_spec.rb:41
显然,这个方法似乎要求“第一”。我理解在这种特殊情况下有点多余,所以我可以删除它,但不是在我知识的一个漏洞周围,我想学习如何正确地做到这一点(对于这种情况)。
任何人都可以帮助我填补空缺吗?
更新
我按照答案中的建议添加了[@topic]数组,但现在我收到了错误:
Failure/Error: put :update, :topic_slug => "some-slug", :topic => {}
Mock "Topic_1001" received unexpected message :slug with (no args)
关于此代码:
def get_topic
@topic = Topic.where(:slug => params[:topic_slug]).first
@topic
end
参数不能改变(至少不能改变)。非常感谢进一步的帮助!
答案 0 :(得分:3)
更改此行
Topic.should_receive(:where).with("some-slug").and_return(@topic)
到这个
Topic.should_receive(:where).with("some-slug").and_return([@topic])
你期望数组但返回一个元素。
答案 1 :(得分:2)
stub_chain
是代码气味,应该作为最后的手段。它将您的规范与实现细节紧密联系在一起,实现细节可能会因重构而发生变化。
我建议这样的事情:
Topic.should_receive(:with_slug).and_return(@topic)
然后将with_slug
方法添加到Topic
,您就可以了。