我想调用一个只返回一条记录的named_scope,但是named_scope返回一个数组,这不是什么大问题,因为我可以用.first链接它。
Model.named_scope(param).first
这是有效的,我正在努力的是如何存根链接的电话。有没有人有关于如何用Rspec模拟实现这个目标的参考或答案?
答案 0 :(得分:16)
我想出了什么。
Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))
允许我给我的控制器打电话:
@client = Client.named_scope(param).first
它有效,但有更好的解决方案吗?
编辑:
rspec 1.2.6的发布允许我们使用stub_chain,这意味着它现在可以是:
Client.stub_chain(:named_scope, :chained_call).and_return(@clients = [mock(Client)])
这是我的头脑,因为总是检查api的具体细节:)
答案 1 :(得分:2)
更好的
版本Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))
将是:
Client.should_receive(:named_scope).with(param).and_return do
record = mock_model(Comm)
record.should_receive(:do_something_else)
[record]
end
答案 2 :(得分:2)
这个问题相当陈旧,因此在如何进行存根方面几乎没有任何改进。现在您可以使用stub_chain方法来存根方法调用链。 例如:
@client = Client.named_scope(param).first
可以用:
Client.stub_chain(:named_scope,:first).and_return(@client = mock(Client))
stub_chaining的更多示例:
describe "stubbing a chain of methods" do
subject { Object.new }
context "given symbols representing methods" do
it "returns the correct value" do
subject.stub_chain(:one, :two, :three).and_return(:four)
subject.one.two.three.should eq(:four)
end
end
context "given a string of methods separated by dots" do
it "returns the correct value" do
subject.stub_chain("one.two.three").and_return(:four)
subject.one.two.three.should eq(:four)
end
end
end
rspecs万岁! :)
答案 3 :(得分:1)
我想这是在控制器规范中?
你自己的建议应该可以正常工作。另一种可能性是在模型中移动named_scope调用,以完全避免该问题。这也符合“胖模型,瘦控制器”的建议。
答案 4 :(得分:0)
我认为你已经完成了瘦控制器的工作,将查询放入一个可以重用的命名范围。这是我开始使用命名范围之前使用的一些代码。
def mock_comm(stubs={})
@mock_comm ||= mock_model(Comm, stubs)
end
describe "responding to GET index" do
it "should expose all comms as @comms" do
Comm.should_receive(:find).with(:all).and_return([mock_comm])
get :index
assigns[:comms].should == [mock_comm]
end
# ...
我可能会编写与您已经完全相似的代码,但也许可以将它放在一个允许我重用它的帮助器中。另一件事是使用一个不同的模拟框架,可能会给你更多的控制。看看Ryan Bates在RSpec上的轨道广播 - 它现在有点旧了,但仍有一些好主意。