所以我有一些代码,粗略地简化后,看起来像这样:
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 answer 的 should
语法似乎在 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/