如果我有一个构造函数调用另一个函数的类,我该如何检查它是否被调用了正确的次数?
class MyClass
def initialize(count)
count.times{self.do_something}
end
def do_something
# whatever
end
end
我想说点什么
n = 4
MyClass.new(n).should_receive(:do_something).exactly(n).times
n = 2
MyClass.new(n).should_receive(:do_something).exactly(n).times
但是失败是因为在do_receive附加到do_someive之前调用了do_something(至少我认为这就是原因)。
expected: 4 times with any arguments
received: 0 times with any arguments
或者从构造函数中调用这样的东西是不对的,我应该重构一下?
此外,这个问题与此问题非常相似:
rspec: How to stub an instance method called by constructor?
但是我希望在过去的5年里,答案比设置存根new
电话的手动实施要好。
答案 0 :(得分:7)
执行此操作的新语法如下:
allow_any_instance_of(ExampleClass).to receive(:example_method).and_return("Example")
expect_any_instance_of(ExampleClass).to receive(:example_method).and_return("Example")
答案 1 :(得分:2)
期望被放置在预期会满足它们的代码之前。
MyClass.any_instance.should_receive(:do_something).exactly(1).time
MyClass.new
这应该有效。
答案 2 :(得分:2)
另一个答案是使用rspec间谍。这里的问题是你必须在事后为你想要的方法创建一个模拟。事实证明这并不难,但你仍然需要列举它们。 and_call_original
是使实现不变的神奇之处。
MyClass.any_instance.stub(:method_name).and_call_original
然后你可以说:
MyClass.new(4).should have_received(:method_name).exactly(4).times
但我仍然希望找到一种不需要你枚举方法的方法。
答案 3 :(得分:0)
这是我提出的最好的,但我不喜欢它:
在Class中创建一个新方法,该方法在已分配但尚未初始化的对象上运行块。我把它放在我的spec文件的before
块中,但是它可能是一个更好的地方:
class Class
def rspec_new(*params, &block)
o = allocate
yield(o) if block
o.__send__(:initialize, *params)
return o
end
end
然后这样称呼:
MyClass.rspec_new(n){|obj| obj.should_receive(:do_something).exactly(n).times}
它似乎工作,但你不能传递一个块到你的构造函数。至少不是你通常的做法。这就是我没有覆盖常规new
方法的原因。