“对象调用方法”的自定义匹配器

时间:2014-12-05 19:37:22

标签: ruby rspec

给定一种方法:

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实现相同的目标,但我也不喜欢这种语法。

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

2 个答案:

答案 0 :(得分: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的完整信息。如果您浏览一下,您可以找到如何添加好的错误消息等,这总是派上用场。

答案 1 :(得分: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