31
class A
  def initialize
    @x = do_something
  end

  def do_something
    42
  end
end

do_something在调用原始实现之前,如何在 rspec 中存根(因此将 42 分配给@x)?当然,在不改变实现的情况下。

4

11 回答 11

22

这是将功能添加到 rspec 的提交- 这是 2008 年 5 月 25 日。有了这个你可以做到

A.any_instance.stub(do_something: 23)

但是,最新的 rspec gem 版本(1.1.11,2008 年 10 月)中没有这个补丁。

这张票表明他们出于维护原因将其拉出,并且尚未提供替代解决方案。

看起来你现在做不到。您必须使用 alias_method 或类似的方法手动破解该类。

于 2008-11-25T21:44:50.403 回答
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
于 2009-12-25T11:47:51.527 回答
11

我不知道如何在规范的模拟框架中做到这一点,但您可以轻松地将其换成 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
于 2008-11-25T03:50:18.683 回答
5

或与RR

stub.any_instance_of(A).do_something { 23 }
于 2008-11-25T04:16:50.067 回答
3

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

allow_any_instance_of(Widget).to receive(:name).and_return("Wibble")
于 2016-07-14T09:39:52.203 回答
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
于 2010-04-22T12:45:47.867 回答
2

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

A.any_instance.stub(do_something: 23)

有关更多详细信息,请参阅文档。(感谢rogerdpack指出现在这是可能的 - 我认为它应该得到自己的答案)

于 2012-08-21T12:31:14.393 回答
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 指出的那样,只需在 new with: 上返回 42 A.stub(:new).and_return(42)或类似的东西。

于 2009-10-11T05:25:56.833 回答
0

这是一个可能不是很优雅但基本上肯定会奏效的想法:

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

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

你去吧!我刚刚在我的一项测试中成功使用了它。

于 2012-05-01T18:24:59.057 回答
0

rspec_candy gem 带有一个在 RSpec 1 和 RSpec 2 中都可以使用的辅助方法stub_any_instance

于 2012-06-10T08:50:28.810 回答
-1

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

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

我知道回答原始海报可能为时已晚,但我还是回答了它以供将来参考,因为我带着同样的问题来到这里,但发现它正在使用最新的 rspec 版本。

于 2009-08-22T17:10:29.260 回答