yield 匹配器

有四个相关的匹配器,允许您指定方法是否产生值,产生值的次数,是否产生带参数的值,以及参数是什么。

注意:您的 expect 块*必须*接受一个参数,该参数随后作为块传递给被测方法。这充当一个“探测器”,允许匹配器检测您的方法是否产生值,以及如果产生值,产生的次数和产生的参数是什么。

背景

给定一个名为“my_class.rb”的文件,其中包含

class MyClass
  def self.yield_once_with(*args)
    yield *args
  end

  def self.yield_twice_with(*args)
    2.times { yield *args }
  end

  def self.raw_yield
    yield
  end

  def self.dont_yield
  end
end

yield_control 匹配器

给定一个名为“yield_control_spec.rb”的文件,其中包含

require './my_class'

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 }

  # deliberate failures
  specify { expect { |b| MyClass.yield_once_with(1, &b) }.not_to yield_control }
  specify { expect { |b| MyClass.dont_yield(&b) }.to yield_control }
  specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control.at_least(2).times }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.twice }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(2).times }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_least(1) }
  specify { expect { |b| MyClass.yield_twice_with(1, &b) }.not_to yield_control.at_most(3).times }
end

我运行rspec yield_control_spec.rb

那么输出应该包含所有这些

13 个示例,7 个失败
期望给定块产生控制
期望给定块不产生控制
期望给定块不产生至少两次控制
期望给定块不产生最多 3 次控制

yield_with_args 匹配器

给定一个名为“yield_with_args_spec.rb”的文件,其中包含

require './my_class'

RSpec.describe "yield_with_args matcher" do
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args }
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args("foo") }
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(String) }
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.to yield_with_args(/oo/) }

  specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args("foo", "bar") }
  specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(String, String) }
  specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(/fo/, /ar/) }

  specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args(17, "baz") }

  # deliberate failures
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args }
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args("foo") }
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(String) }
  specify { expect { |b| MyClass.yield_once_with("foo", &b) }.not_to yield_with_args(/oo/) }
  specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.not_to yield_with_args("foo", "bar") }
  specify { expect { |b| MyClass.yield_once_with("foo", "bar", &b) }.to yield_with_args(17, "baz") }
end

我运行rspec yield_with_args_spec.rb

那么输出应该包含所有这些

14 个示例,6 个失败
期望给定块不产生带参数的值,但产生了
期望给定块不产生带参数的值,但产生了预期参数
期望给定块产生带参数的值,但产生了意外参数

yield_with_no_args 匹配器

给定一个名为“yield_with_no_args_spec.rb”的文件,其中包含

require './my_class'

RSpec.describe "yield_with_no_args matcher" do
  specify { expect { |b| MyClass.raw_yield(&b) }.to yield_with_no_args }
  specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_with_no_args }
  specify { expect { |b| MyClass.yield_once_with("a", &b) }.not_to yield_with_no_args }

  # deliberate failures
  specify { expect { |b| MyClass.raw_yield(&b) }.not_to yield_with_no_args }
  specify { expect { |b| MyClass.dont_yield(&b) }.to yield_with_no_args }
  specify { expect { |b| MyClass.yield_once_with("a", &b) }.to yield_with_no_args }
end

我运行rspec yield_with_no_args_spec.rb

那么输出应该包含所有这些

6 个示例,3 个失败
期望给定块不产生无参数的值,但产生了
期望给定块产生无参数的值,但没有产生
期望给定块产生无参数的值,但产生了带参数的值:["a"]

yield_successive_args 匹配器

给定一个名为“yield_successive_args_spec.rb”的文件,其中包含

def array
  [1, 2, 3]
end

def array_of_tuples
  [[:a, :b], [:c, :d]]
end

RSpec.describe "yield_successive_args matcher" do
  specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2, 3) }
  specify { expect { |b| array_of_tuples.each(&b) }.to yield_successive_args([:a, :b], [:c, :d]) }
  specify { expect { |b| array.each(&b) }.to yield_successive_args(Integer, Integer, Integer) }
  specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2) }

  # deliberate failures
  specify { expect { |b| array.each(&b) }.not_to yield_successive_args(1, 2, 3) }
  specify { expect { |b| array_of_tuples.each(&b) }.not_to yield_successive_args([:a, :b], [:c, :d]) }
  specify { expect { |b| array.each(&b) }.not_to yield_successive_args(Integer, Integer, Integer) }
  specify { expect { |b| array.each(&b) }.to yield_successive_args(1, 2) }
end

我运行rspec yield_successive_args_spec.rb

那么输出应该包含所有这些

8 个示例,4 个失败
期望给定块不产生带参数的连续值,但产生了预期参数
期望给定块产生带参数的连续值,但产生了意外参数