2013-08-05 43 views
4

如果我有一个构造函数调用另一个函数的类,我该如何检查它是否被调用并调用了正确的次数?如何检查对rspec中构造函数调用的方法的调用?

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: How to stub an instance method called by constructor?

但我希望在过去5年中,答案已经变得比建立一个存根new通话的手动实现更好的。

回答

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

See the docs

2

预期意味着放在预期会遇到它们的代码之前。

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

这应该有效。

+0

,但我不希望它在任何实例。我想在这个特定的实例上。我可能不知道我会有多少个实例,每个实例应该能够接到1个呼叫,有些可能会得到另一个实例(对不起,这不在我的例子中) - 更新的例子。我知道这是人为的,但我试图不发表大量的代码。 – xaxxon

+0

我明白你的意思了,我会更新我的答案。 –

+0

你的'do_something'方法是否复杂?在我看来,你应该在初始化之后测试对象的状态,而不是期望在初始化时应该调用一个方法。 –

0

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

创建类的新方法,它运行在分配的块,但尚未initialize'd对象。我在规范文件中把这个在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方法。

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 

我还是很乐意地发现,不需要你枚举方法,虽然方式。

相关问题