rspec:如何存根构造函数调用的实例方法?

时间:2008-11-25 03:34:40

标签: ruby rspec stub

class A
  def initialize
    @x = do_something
  end

  def do_something
    42
  end
end

如何在调用原始实现之前在rspec中存根do_something(从而将42分配给@x)?当然,并没有改变实施。

11 个答案:

答案 0 :(得分:22)

Here's the commit which adds the feature to rspec - 这是2008年5月25日。你可以这样做

A.any_instance.stub(do_something: 23)

然而,rspec的最新宝石版本(1.1.11,2008年10月)中没有此补丁。

This ticket表示由于维护原因他们将其拉出来,并且尚未提供替代解决方案。

此时看起来你不能做到这一点。你必须使用alias_method手动破解类。

答案 1 :(得分:16)

我在http://pivotallabs.com/introducing-rr/

上找到了这个解决方案
new_method = A.method(:new)

A.stub!(:new).and_return do |*args|
  a = new_method.call(*args)
  a.should_receive(:do_something).and_return(23)
  a
end

答案 2 :(得分:11)

我不知道如何在spec的模拟框架中执行此操作,但您可以轻松地将其替换为mocha以执行以下操作:

# should probably be in spec/spec_helper.rb
Spec::Runner.configure do |config|
  config.mock_with :mocha
end

describe A, " when initialized" do
  it "should set x to 42" do
    A.new.x.should == 42
  end
end

describe A, " when do_something is mocked" do
  it "should set x to 23" do
    A.any_instance.expects(:do_something).returns(23)
    A.new.x.should == 23
  end
end

答案 3 :(得分:5)

RR

stub.any_instance_of(A).do_something { 23 }

答案 4 :(得分:3)

在今天最新版本的RSpec中 - 3.5你可以:

allow_any_instance_of(Widget).to receive(:name).and_return("Wibble")

答案 5 :(得分:2)

我确实喜欢Denis Barushev的回答。而且我想建议只进行一次化妆改变,使new_method变量不必要。 Rspec确实使用了存根方法,因此可以使用proxied_by_rspec__前缀:

访问它们

A.stub!(:new).and_return do |*args|
  a = A.proxied_by_rspec__new(*args)
  a.should_receive(:do_something).and_return(23)
  a
end

答案 6 :(得分:2)

在RSpec 2.6或更高版本中,您可以使用

A.any_instance.stub(do_something: 23)

有关详细信息,请参阅the docs。 (感谢rogerdpack指出现在已经可以了 - 我认为它应该得到自己的答案)

答案 7 :(得分:0)

要存根实例方法,您可以执行以下操作:

before :each do
  @my_stub = stub("A")
  @my_stub.should_receive(:do_something).with(no_args()).and_return(42)
  @my_stub.should_receive(:do_something_else).with(any_args()).and_return(true)
  A.stub(:new).and_return(my_stub)
end

但正如pschneider指出的那样,只需返回新的42: A.stub(:new).and_return(42)或类似的东西。

答案 8 :(得分:0)

这是一个可能不是很优雅的想法,但基本上肯定会起作用:

创建一个继承要测试的类的小类,覆盖initialize方法,并在在初始化中创建存根后调用super ,如下所示:

it "should call during_init in initialize" do
  class TestClass < TheClassToTest
    def initialize
      should_receive(:during_init)
      super
    end
  end
  TestClass.new
end

你去吧!我只是在我的一次测试中成功使用了它。

答案 9 :(得分:0)

rspec_candy gem附带一个stub_any_instance辅助方法,适用于RSpec 1和RSpec 2。

答案 10 :(得分:-1)

在我的rspec(1.2.2)版本中,我可以这样做:

A.should_receive(:new).and_return(42)

我知道回复原版海报可能要迟到了,但无论如何我都会回答它以供将来参考,因为我带着同样的问题来到这里,但发现它正在研究最新的rspec版本。