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

发布于 2024-07-09 20:16:42 字数 215 浏览 9 评论 0 原文

class A
  def initialize
    @x = do_something
  end

  def do_something
    42
  end
end

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

class A
  def initialize
    @x = do_something
  end

  def do_something
    42
  end
end

How can I stub do_something in rspec, before the original implementation is called (thus assigning 42 to @x)? And without changing the implementation, of course.

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

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

发布评论

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

评论(11

杯别 2024-07-16 20:16:42

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

A.any_instance.stub(do_something: 23)

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

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

看起来你目前还不能做到这一点。 您必须使用 alias_method 或类似方法手动破解该类。

Here's the commit which adds the feature to rspec - This was on May 25 2008. With this you can do

A.any_instance.stub(do_something: 23)

However, the latest gem version of rspec (1.1.11, October 2008) doesn't have this patch in it.

This ticket states that they yanked it out for maintenance reasons, and an alternative solution hasn't yet been provided.

Doesn't look like you can do it at this point. You'll have to hack the class manually using alias_method or somesuch.

木落 2024-07-16 20:16:42

我在 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

I've found this solution on 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
你是暖光i 2024-07-16 20:16:42

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

# 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

I don't know how to do that in spec's mock framework, but you can easily swap it out for mocha to do the following:

# 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
情域 2024-07-16 20:16:42

或使用 RR

stub.any_instance_of(A).do_something { 23 }

or with RR:

stub.any_instance_of(A).do_something { 23 }
埋情葬爱 2024-07-16 20:16:42

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

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

In the latest version of RSpec as of today - 3.5 you can:

allow_any_instance_of(Widget).to receive(:name).and_return("Wibble")
岁月蹉跎了容颜 2024-07-16 20:16:42

我确实喜欢丹尼斯·巴鲁舍夫的回答。 我只想建议一项外观上的更改,使 new_method 变量变得不必要。 Rspec 对存根方法进行 munge,以便可以使用 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

I do like Denis Barushev answer. And I'd like to suggest only one cosmetic change which makes new_method variable unnecessary. Rspec does munge on stubbed methods, so that they can be accessed with proxied_by_rspec__ prefix:


A.stub!(:new).and_return do |*args|
  a = A.proxied_by_rspec__new(*args)
  a.should_receive(:do_something).and_return(23)
  a
end
戒ㄋ 2024-07-16 20:16:42

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

A.any_instance.stub(do_something: 23)

参见 文档了解更多详细信息。 (感谢 rogerdpack 指出这现在是可能的 - 我认为它应该有一个自己的答案)

In RSpec 2.6 or later you can use

A.any_instance.stub(do_something: 23)

See the docs for more details. (Thanks to rogerdpack for pointing out that this is now possible - I thought it deserved an answer of its own)

将军与妓 2024-07-16 20:16:42

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

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 上返回 42 即可:
A.stub(:new).and_return(42) 或类似的东西。

To stub an instance method, you can do something like this:

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

But as pschneider pointed out, just return 42 on new with:
A.stub(:new).and_return(42) or something to that effect.

时光清浅 2024-07-16 20:16:42

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

创建一个继承要测试的类的小类,重写初始化方法并调用 super after

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

就这样! 我刚刚在我的一项测试中成功地使用了它。

Here is an idea which might not be very elegant but is basically sure to work:

Create a tiny class that inherits the class you want to test, override the initialize method and call super after having created the stubs in the initialize, like so:

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

And there you go! I just used this successfully in one of my tests.

梨涡少年 2024-07-16 20:16:42

rspec_candy gem 附带了一个 stub_any_instance 辅助方法,可以在 RSpec 1 和R规格2。

The rspec_candy gem comes with a stub_any_instance helper method that works in both RSpec 1 and RSpec 2.

深白境迁sunset 2024-07-16 20:16:42

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

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

我知道回答原始海报可能已经太晚了,但我无论如何都会回答以供将来参考,因为我带着同样的问题来到这里,但弄清楚了它正在开发最新的 rspec 版本。

In my version of rspec (1.2.2) I can do this:

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

I know it is probably to late to answer to the original poster, but I answer it anyway for future reference, as I came here with the same question but figure it out it was working on the latest rspec version.

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