ruby-on-rails - rspec any_instance stub 不会重新启动旧实例

标签 ruby-on-rails ruby rspec

我最近在 Ruby 2.0、Rails 4 和 Rspec 2.13.1 中发现了这种奇怪的行为

当我使用ClassName.any_instance.stub(:method_name) stub 实例方法时,它会正确 stub 和我创建的过去的实例。但是,当我通过更改返回值重新设置它时,旧实例返回旧的 stub 值,而不是新的 stub 值。

例如,我有这个虚拟类定义

class A
  def test(x)
    return x
  end
end

这个测试描述了行为:

it 'strange stubbing behavior' do
  inst = A.new
  inst.test(1).should eq 1                         #passes
  A.any_instance.stub(:test).and_return(10)
  inst.test(0).should eq 10

  A.any_instance.unstub(:test)                     #has no effect
  A.any_instance.stub(:test).and_return(100)

  inst.test(0).should eq 100                       #expects 100, got 10

  A.any_instance.stub(:test) do |a|
    a + 2
  end
  inst.test(3).should eq 5   #also fails           # also got 10
end

为什么 rspec 会这样?这是定义的行为吗?如果是这样,那么重新启动旧实例的正确方法是什么。或者这是一个错误?

编辑:在其他人给出“质疑问题”的答案之前,我想指出,我确实通过重新思考规范并重新组织它们解决了我最初的问题。然而,我仍然很好奇为什么 RSpec 会这样表现

最佳答案

简而言之,当您使用 any_instance.unstub 在实例上调用 stub 时,RSpec 确实不会取消 stub 现有实例。同样,正如您所发现的,使用 any_instance.stub 进行 stub 操作将不适用于之前 stub /调用的实例。

但是,如果您不调用或显式取消 stub 现有实例,则任何带有 any_instance 的新 stub 都将在该实例上按预期工作。例如,对您的示例进行以下修改即可工作。

it 'strange stubbing behavior' do
  inst = A.new
  inst.test(1).should eq 1                         #passes
  A.any_instance.stub(:test).and_return(10)
  # SKIP THE INVOCATION SO TEST WILL PASS
  # inst.test(0).should eq 10

  A.any_instance.unstub(:test)                     #has no effect (on existing instances)

  A.any_instance.stub(:test).and_return(100)

  inst.test(0).should eq 100                       #expects 100, got 10

  inst.unstub(:test) # UNSTUB INSTANCE SO TEST WILL PASS                                                            
  A.any_instance.stub(:test) do |a|
    a + 2
  end
  inst.test(3).should eq 5   #also fails           # also got 10
end

不确定这是否是预期的行为,但提交了 issue为了它。 RSpec Cucumber 测试,可在 https://www.relishapp.com/rspec/rspec-mocks/docs/method-stubs/stub-on-any-instance-of-a-class#any-instance-unstub 查看,仅测试 unstub 是否适用于新实例。

(向@Theresa Luu 表示感谢,感谢她在这方面的帮助。)

关于ruby-on-rails - rspec any_instance stub 不会重新启动旧实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18092601/

相关文章:

ruby-on-rails - 查找所有没有关联 has_many 对象的对象

ruby-on-rails - 转储 Heroku 数据库以在本地 seed.rb 中使用的最简单方法?

ruby-on-rails - time_ago_in_words 和本地化

ruby - 用于异步非阻塞调用的 AWS ruby​​ sdk

ruby-on-rails - 如何使用 Rails 上的参数动态更改模型的字段?

testing - 具有设计身份验证的 rspec Controller 测试

ruby-on-rails - Active Admin 使用预设集合批量编辑产品

ruby-on-rails - Rails 和 carrierwave - 可以上传图片,但不能上传 pdf

ruby-on-rails - 如何使用实例变量测试部分

ruby-on-rails - 如何在 Ruby 中使用 RSpec 通过 Windows 命令提示符获取颜色?