ruby - 当一个对象的构造函数构建另一个对象时 stub

标签 ruby constructor rspec stubbing rr

所以我有一些代码,粗略地简化后,看起来像这样:

class B
  def initialize opts
    @opts = opts
  end
end

class A
  def initialize opts
    # defaults etc applied to opts
    @b = B.new opts
  end
end

换句话说,当我用选项初始化 A 时,它会创建一个 B 并将一组修改后的选项传递给它。

我想测试 B.new 是否获得正确的参数。现在,我正在这样做,使用 RSpec/RR:

@b = Object.new
# stub methods on @b here
stub(B).new { |options|
  options[:foo].should == 'whatever'
  @b
}
A.new({:foo => 'whatever'})

但这有两个问题。

首先,我无法使用实际选项实例化 B 的实际副本。如果我在 block 内调用 B.new,它会调用 stub 版本并循环直到堆栈弹出。我可以在 stub 之前设置@b = B.new,但我还不知道将要传入的选项,这违背了测试的要点。

(在有人叫我出来之前:是的,在严格的单元测试教条中,A 的测试应该剔除 B 中的任何方法,并且需要剔除很多意味着你的代码首先是不好的。)

其次,将 should 放在测试的设置中,而不是放在单独的 it ... do ... end 之后的 block 中,感觉不对.但由于我无法创建实际的 B(见上文),我也无法真正询问其构建后的状态。

有什么想法吗?

最佳答案

来自 Marc-André Lafortune's answershould 语法似乎在 RSpec 3 中已弃用。但是,以下 expect 语法似乎有效:

expect(B).to receive(:new).with(foo: 'whatever')

请注意,如果您希望 B.new 返回特定实例(例如测试替身),您可以使用 and_return:

b = instance_double(B)
expect(B).to receive(:new).with(foo: 'whatever').and_return(b)

关于ruby - 当一个对象的构造函数构建另一个对象时 stub ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11356096/

相关文章:

ruby-on-rails - 字符串中的两个变量

ruby - Ruby `exit!` 函数似乎调用了与文档相反的退出处理程序

java - 构造函数中的可重写方法调用有什么问题?

ruby - Selenium ruby​​ 检查 webelement 是否可点击?

ruby-on-rails - RoR - 外键设置为 nil 后记录保存失败

unit-testing - RSpec 场景大纲 : Multiple Test Cases

arrays - Ruby:排序数组,跳过第一个元素

ruby-on-rails - Rails 协会 - 至少有一个

java - Stackoverflow 是由简单的代码引起的

c# - 用于序列化的无参数构造函数与具有默认参数的构造函数相结合,为什么它有效?