使用 Rspec 存根链式方法

发布于 2024-07-15 04:22:35 字数 207 浏览 7 评论 0原文

我想调用一个只返回一个记录的named_scope,但是named_scope返回一个数组,这不是什么大问题,因为我可以将它与.first链接起来:

Model.named_scope(param).first

这有效,我正在努力解决的是如何存根链接的称呼。 有没有人有关于我如何通过 Rspec 模拟实现这一目标的参考或答案?

I want to call a named_scope that will only return one record, but the named_scope returns an array, that's not a big deal as I can just chain it with .first:

Model.named_scope(param).first

and this works, what I am struggling with is how to stub the chained call. Does anyone have a reference or an answer on how I would go about achieving this with Rspec mocking?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

被你宠の有点坏 2024-07-22 04:22:35

我想出了一些办法。

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 来了解细节:)

I figured something out.

Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))

which allows me to call my controller:

@client = Client.named_scope(param).first

It works, but is there a better solution?

EDIT:

The release of rspec 1.2.6 allows us to use stub_chain meaning it can now be:

Client.stub_chain(:named_scope, :chained_call).and_return(@clients = [mock(Client)])

This was top of my head, as always check the api for specifics :)

笑叹一世浮沉 2024-07-22 04:22:35

更好的版本

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

Better version of

Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))

will be:

Client.should_receive(:named_scope).with(param).and_return do
  record = mock_model(Comm)
  record.should_receive(:do_something_else)
  [record]  
end
给不了的爱 2024-07-22 04:22:35

这个问题很老了,因此在如何完成存根方面几乎没有任何增强。 现在您可以使用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万岁!!! :)

The question is quite old and hence there are few enhancements in how stubbing can be done. Now you can use stub_chain method to stub a chain of method calls.
For example:

@client = Client.named_scope(param).first

can be stubbed with:

Client.stub_chain(:named_scope,:first).and_return(@client = mock(Client))

More examples of 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

or please have a look at:

Long live the rspecs!!! :)

迷雾森÷林ヴ 2024-07-22 04:22:35

我想这是在控制器规范中?

你自己的建议应该很好用。 另一种可能性是将named_scope调用移到模型中,以完全避免该问题。 这也符合“胖模型,瘦控制器”的建议。

I suppose this is in a controller spec?

Your own suggestion should work fine. Another possibility is to move the named_scope call inside your model, to avoid the issue entirely. This would also be in line with the "fat models, thin controllers" advice.

夜空下最亮的亮点 2024-07-22 04:22:35

我认为您已经通过将查询放入可以重用的命名范围中来完成瘦控制器的工作。 这是我在开始使用命名范围之前使用的一些代码。

  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 上的 Railscast - 现在有点旧了,但仍然有一些好主意。

I think you've already done the thin controller thing by putting the query into a named scope where it can be reused. Here is some code I used before I started using named scopes.

  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
# ...

I would probably write code quite similar to what you have already, but maybe put it in a helper that allows me to reuse it. The other thing is to use a different mocking framework that maybe gives you more control. Have a look at Ryan Bates' railscast on RSpec - it's a bit old now but still some good ideas in there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文