代码之家  ›  专栏  ›  技术社区  ›  nitecoder

带Rspec的stubing链式方法

  •  11
  • nitecoder  · 技术社区  · 17 年前

    我想调用一个只返回一条记录的命名\u作用域,但命名\u作用域返回一个数组,这不是什么大问题,因为我可以将它链接起来。首先:

    Model.named_scope(param).first
    

    这是可行的,我正在努力解决的是如何存根链式调用。关于我将如何通过Rspec mocking实现这一点,有人有参考或答案吗?

    5 回复  |  直到 14 年前
        1
  •  16
  •   nitecoder    17 年前

    我想出了一些办法。

    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版本允许我们使用存根链,这意味着它现在可以:

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

        2
  •  2
  •   luacassus    15 年前

    更好的版本

    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
    
        3
  •  2
  •   Sahil Dhankhar    13 年前

    这个问题已经很老了,因此很少有关于如何进行存根的增强。现在您可以使用stub\u chain方法来存根方法调用链。 例如:

    @client = Client.named_scope(param).first

    可以用以下内容来代替:

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

    存根链接的更多示例:

    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:

    rspecs万岁!!!:)

        4
  •  1
  •   Antti Tarvainen    17 年前

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

    你自己的建议应该行得通。另一种可能是将命名的_范围调用移动到模型中,以完全避免问题。这也符合“胖模特,瘦控制器”的建议。

        5
  •  0
  •   Ghoti    17 年前

      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——它现在有点老了,但仍然有一些好主意。