测试方法是否占用块

时间:2017-09-19 18:35:08

标签: ruby rspec

如何验证Foobar#some_method是否占用了一个块。与Foobar.new.respond_to?(:some_method)

相似的东西
class Foobar
  def some_method
    yield
  end
end

为什么吗

这对测试合同界面很有用。确保方法I stub具有未更改的API。

我尝试过的方式

mth = Foobar.new.method(:some_method)
mth.parameters

这将返回一个参数列表(Rspec基本上使用了什么)。如果我有一个像这样的块参数,它就可以工作:

def some_method(&blk)
end

但是,如果某个方法使用yield,我就不会从#parameters获得任何内容。

这是为了确保与丑陋的外部世界的接口添加规范。所以我知道如何使用方法。但如果有API更改,我希望规格失败。

1 个答案:

答案 0 :(得分:3)

  

如何验证Foobar#some_method是否需要阻止。

ruby​​中的每个方法都需要(可以)一个块。它可能只是选择不屈服。那么你需要检查的是,我认为:如果方法产生与否。

RSpec有许多收益预期:https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/yield-matchers

RSpec.describe "yield_control matcher" do
  specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control }
  specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_control }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.twice }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.exactly(2).times }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_least(1) }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_most(3).times }

end

所以对于你的情况,它应该是这样的:

expect{ foobar.some_method }.to yield_control