4

如果我有一个构造函数调用另一个函数的类,我如何检查它是否被调用以及正确的次数?

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_something 的调用发生在 should_receive 附加到它之前(至少我认为这就是原因)。

expected: 4 times with any arguments
received: 0 times with any arguments

或者从构造函数中调用这样的东西是错误的,我应该重构?

此外,这个问题与这个问题非常相似:

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

但我希望在过去的 5 年里,答案比手动实现存根new调用更好。

4

4 回答 4

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")

查看文档

于 2014-10-22T16:14:02.023 回答
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

不过,我仍然很想找到一种不需要您枚举方法的方法。

于 2013-08-05T19:53:40.513 回答
2

期望应该放在期望满足它们的代码之前。

MyClass.any_instance.should_receive(:do_something).exactly(1).time
MyClass.new

那应该行得通。

于 2013-08-05T18:06:40.707 回答
0

这是我想出的最好的,但我不喜欢它:

在 Class 中创建一个新方法,该方法在已分配但尚未初始化的对象上运行一个块。我把它放在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方法。

于 2013-08-05T19:17:56.083 回答