2014-12-05 64 views
0

给予相同的方法:自定义匹配器的“关于对象调用方法”

class MyClass 
    def method_that_calls_stuff 
    method2("some value") 
    end 
end 

我想就像定义一个期望:

my_object = MyClass.new 
expect{ my_object.method_that_calls_stuff }.to call(:method2).on(my_object).with("some value") 

我知道我能做到同样的事情使用rspec-mocks,但我不喜欢那种语法。

我该如何定义一个这样的匹配器(或者更好,有人已经写了一个)?

回答

1

随着新的语法虽然你可以得到

instance = MyClass.new 
expect(instance).to receive(:method2).with("some value") 
instance.method_that_calls_stuff 

但如果你真的想要的匹配,你可以做

RSpec::Matchers.define(:call) do |method| 
    match do |actual| 
    expectation = expect(@obj).to receive(method) 
    if @args 
     expectation.with(@args) 
    end 
    actual.call 
    true 
    end 

    chain(:on) do |obj| 
    @obj = obj 
    end 

    chain(:with) do |args| 
    @args = args 
    end 

    def supports_block_expectations? 
    true 
    end 
end 

注意with是可选的,因为您可能想调用没有任何参数的方法。

您可以获得关于如何构建自定义匹配器here以及流畅的接口/链接here和块支持here的完整信息。如果你浏览一下,你可以找到如何添加漂亮的错误消息等,这总是派上用场。

+0

太棒了。谢谢。 – 2014-12-08 17:53:08

0

我没有看到method2正在某个对象上被调用(是否被隐式调用?)。但我通常把它写这样的:

it 'should call method2 with some value' do 
    MyClass.should_receive(:method2).with("some value") 
    MyClass.method_that_calls_stuff 
    # or 
    # @my_object.should_receive(:method2).with("some value") 
    # @my_object.method_that_calls_stuff 
end 
+0

是的,这也是我使用的语法。我想要一个Matcher,它可以让我设定期望,并在一个声明中调用方法。 – 2014-12-05 21:16:54