2014-12-05 65 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