匹配参数

使用 with 指定预期的参数。通过 with 约束的 消息预期 只有在使用匹配参数调用时才会满足。对于 允许的消息,只有在参数匹配时才会使用预置响应。

要匹配... ...使用类似的表达式 ...这将匹配以下调用
文字参数 with(1, true) foo(1, true)
文字参数,其中一个为哈希 with(1, {x: 1, y: 2}) `foo(1, x: 1, y: 2)(最后一个参数为哈希)
关键字参数 with(x: 1, y: 2) foo(x: 1, y: 2)(其中 x 和 y 为关键字)
支持案例等式(===)的任何内容 with(/bar/) foo("barn")
任何参数列表 with(any_args) foo()
foo(1)
foo(:bar, 2)
任何参数子列表(如参数 splat) with(1, any_args) foo(1)
foo(1, :bar, :bazz)
空参数列表 with(no_args) foo()
给定位置参数的任何内容 with(3, anything) foo(3, nil)
foo(3, :bar)
针对接口 with(duck_type(:each)) foo([])
布尔值 with(3, boolean) foo(3, true)
foo(3, false)
哈希的子集 with(hash_including(:a => 1)) foo(:a => 1, :b => 2)
哈希的排除子集 with(hash_excluding(:a => 1)) foo(:b => 2)
数组的子集 with(array_including(:a, :b)) foo([:a, :b, :c])
数组的排除子集 with(array_excluding(:a, :b)) foo([:c, :d])
特定类的实例 with(instance_of(Integer)) foo(3)
祖先列表中包含给定模块的对象 with(kind_of(Numeric)) foo(3)
具有匹配属性的对象 with(having_attributes(:a => 1)) foo(:a => 1, :b => 2)
任何 RSpec 匹配器 with(<matcher>) foo(<匹配的对象>)

基本示例

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

RSpec.describe "Constraining a message expectation using with" do
  let(:dbl) { double }
  before { expect(dbl).to receive(:foo).with(1, anything, /bar/) }

  it "passes when the args match" do
    dbl.foo(1, nil, "barn")
  end

  it "fails when the args do not match" do
    dbl.foo(1, nil, "other")
  end
end

我运行 rspec basic_example_spec.rb

那么它应该失败并显示以下输出

2 个示例,1 个失败
Failure/Error: dbl.foo(1, nil, “other”)
#收到 :foo,但参数意外
预期: (1, anything, /bar/)
实际: (1, nil, “other”)

使用关键字参数

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

class WithKeywords
  def foo(bar: "")
  end
end

RSpec.describe "Constraining a message expectation using with" do
  let(:dbl) { instance_double(WithKeywords) }
  before { expect(dbl).to receive(:foo).with(bar: "baz") }

  it "passes when the args match" do
    dbl.foo(bar: "baz")
  end

  it "fails when the args do not match" do
    dbl.foo(bar: "incorrect")
  end
end

我运行 rspec keyword_example_spec.rb

那么它应该失败并显示以下输出

2 个示例,1 个失败
Failure/Error: dbl.foo(bar: “incorrect”)
#收到 :foo,但参数意外
预期: ({:bar=>“baz”})
实际: ({:bar=>“incorrect”})

在区分哈希和关键字参数的 Ruby 版本中使用关键字参数

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

class WithKeywords
  def foo(bar: "")
  end
end

RSpec.describe "Constraining a message expectation using with" do
  let(:dbl) { instance_double(WithKeywords) }
  before { expect(dbl).to receive(:foo).with(bar: "baz") }

  it "fails when the args do not match due to a hash" do
    dbl.foo({bar: "also incorrect"})
  end
end

我运行 rspec keyword_example_spec.rb

那么它应该失败并显示以下输出

1 个示例,1 个失败
Failure/Error: dbl.foo({bar: “also incorrect”})
#收到 :foo,但参数意外
预期: ({:bar=>“baz”})(关键字参数)
实际: ({:bar=>“also incorrect”})(选项哈希)

使用 RSpec 匹配器

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

RSpec.describe "Using a RSpec matcher" do
  let(:dbl) { double }
  before { expect(dbl).to receive(:foo).with(a_collection_containing_exactly(1, 2)) }

  it "passes when the args match" do
    dbl.foo([2, 1])
  end

  it "fails when the args do not match" do
    dbl.foo([1, 3])
  end
end

我运行 rspec rspec_matcher_spec.rb

那么它应该失败并显示以下输出

2 个示例,1 个失败
Failure/Error: dbl.foo([1, 3])
#收到 :foo,但参数意外
预期:(包含 1 和 2 的集合)
实际: ([1, 3])

使用 satisfy 进行复杂的自定义预期

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

RSpec.describe "Using satisfy for complex custom expecations" do
  let(:dbl) { double }

  def a_b_c_equals_5
    satisfy { |data| data[:a][:b][:c] == 5 }
  end

  it "passes when the expectation is true" do
    expect(dbl).to receive(:foo).with(a_b_c_equals_5)
    dbl.foo({ :a => { :b => { :c => 5 } } })
  end

  it "fails when the expectation is false" do
    expect(dbl).to receive(:foo).with(a_b_c_equals_5)
    dbl.foo({ :a => { :b => { :c => 3 } } })
  end
end

我运行 rspec rspec_satisfy_spec.rb

那么它应该失败并显示以下输出

2 个示例,1 个失败
Failure/Error: dbl.foo({ :a => { :b => { :c => 3 } } })
#收到 :foo,但参数意外
预期:(满足表达式 data[:a][:b][:c] == 5
实际: ({:a=>{:b=>{:c=>3}}})

使用自定义匹配器

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

RSpec::Matchers.define :a_multiple_of do |x|
  match { |actual| (actual % x).zero? }
end

RSpec.describe "Using a custom matcher" do
  let(:dbl) { double }
  before { expect(dbl).to receive(:foo).with(a_multiple_of(3)) }

  it "passes when the args match" do
    dbl.foo(12)
  end

  it "fails when the args do not match" do
    dbl.foo(13)
  end
end

我运行 rspec custom_matcher_spec.rb

那么它应该失败并显示以下输出

2 个示例,1 个失败
Failure/Error: dbl.foo(13)
#收到 :foo,但参数意外
预期:(3 的倍数)
实际: (13)

根据参数不同地响应

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

RSpec.describe "Using #with to constrain responses" do
  specify "its response depends on the arguments" do
    dbl = double

    # Set a default for any unmatched args
    allow(dbl).to receive(:foo).and_return(:default)

    allow(dbl).to receive(:foo).with(1).and_return(1)
    allow(dbl).to receive(:foo).with(2).and_return(2)

    expect(dbl.foo(0)).to eq(:default)
    expect(dbl.foo(1)).to eq(1)
    expect(dbl.foo(2)).to eq(2)
  end
end

我运行 rspec responding_differently_spec.rb

那么这些示例应该全部通过。