RSpec 模拟 ActiveRecord Find First 与Where 的问题
我正在尝试整理我的控制器的 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
显然,这似乎是“first”的方法调用。我知道在这种特殊情况下有点多余,所以我可以删除它,但我不想绕过我知识中的漏洞,而是想学习如何正确地做到这一点(对于这种情况)。
谁能帮我填补我的坑吗?
更新:
我按照答案中的建议添加了 [@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
参数无法更改(至少不能更改)。非常感谢进一步的帮助!
I am trying to sort out my RSpec tests for a controller of mine, but its not working and I need some help figuring it out.
My Rspec is:
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
The controller logic I am trying to test is:
def get_topic
@topic = Topic.where(:slug => params[:topic_slug]).first
@topic
end
But the output I am getting is:
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
Obviously, it seems like the method call for "first". I understand is a bit redundant in this particular case, so I could remove it, but rather than hack around a hole in my knowledge, I'd like to learn how to do it properly (for this scenario).
Can anyone help me fill my hole?
Update:
I added the [@topic] array as suggested in the answers, but now I am getting the error:
Failure/Error: put :update, :topic_slug => "some-slug", :topic => {}
Mock "Topic_1001" received unexpected message :slug with (no args)
With respect to this code:
def get_topic
@topic = Topic.where(:slug => params[:topic_slug]).first
@topic
end
The parameters can't be changed (at least not trivially). Further assistance greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将此行
Topic.should_receive(:where).with("some-slug").and_return(@topic)
更改为
Topic.should_receive(:where).with("some- slug").and_return([@topic])
你期望数组但返回一个元素。
Change this line
Topic.should_receive(:where).with("some-slug").and_return(@topic)
to this
Topic.should_receive(:where).with("some-slug").and_return([@topic])
you expect array but return one element.
stub_chain
是一种代码味道,应该被视为最后的手段。它将您的规范与实现细节紧密联系在一起,而实现细节可能会通过重构而发生变化。我建议这样:
然后向
Topic
添加一个with_slug
方法,然后就可以开始了。stub_chain
is a code smell and should be treated as a last resort. It ties your spec very tightly to implementation detail, which is subject to change via refactoring.I'd recommend something like this:
Then add a
with_slug
method toTopic
and you're good to go.