メインコンテンツまでスキップ

引数のマッチング

with を使用して、期待される引数を指定します。with で制約を設けた メッセージの期待値 は、 マッチする引数で呼び出された場合にのみ満たされます。許可されたメッセージ のための事前準備された応答は、引数が一致する場合にのみ使用されます。

  | To match...                                         | ...use an expression like:         | ...which matches calls like:                        |
|-----------------------------------------------------|------------------------------------|-----------------------------------------------------|
| Literal arguments | `with(1, true)` | `foo(1, true)` |
| Literal arguments where one is a hash | `with(1, {x: 1, y: 2})` | `foo(1, x: 1, y: 2) (where last argument is a hash) |
| Keyword arguments | `with(x: 1, y: 2)` | `foo(x: 1, y: 2)` (where x and y are keywords) |
| Anything that supports case equality (`===`) | `with(/bar/)` | `foo("barn")` |
| Any list of args | `with(any_args)` | `foo()`</br>`foo(1)`</br>`foo(:bar, 2)` |
| Any sublist of args (like an arg splat) | `with(1, any_args)` | `foo(1)`</br>`foo(1, :bar, :bazz)` |
| An empty list of args | `with(no_args)` | `foo()` |
| Anything for a given positional arg | `with(3, anything)` | `foo(3, nil)`</br>`foo(3, :bar)` |
| Against an interface | `with(duck_type(:each))` | `foo([])` |
| A boolean | `with(3, boolean)` | `foo(3, true)`</br>`foo(3, false)` |
| A subset of a hash | `with(hash_including(:a => 1))` | `foo(:a => 1, :b => 2)` |
| An excluded subset of a hash | `with(hash_excluding(:a => 1))` | `foo(:b => 2)` |
| A subset of an array | `with(array_including(:a, :b))` | `foo([:a, :b, :c])` |
| An excluded subset of an array | `with(array_excluding(:a, :b))` | `foo([:c, :d])` |
| An instance of a specific class | `with(instance_of(Integer))` | `foo(3)` |
| An object with a given module in its ancestors list | `with(kind_of(Numeric))` | `foo(3)` |
| An object with matching attributes | `with(having_attributes(:a => 1))` | `foo(:a => 1, :b => 2)` |
| Any RSpec matcher | `with(<matcher>)` | `foo(<object that matches>)` |

基本的な例

次の内容で "basic_example_spec.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 examples, 1 failure                                         |
| |
| Failure/Error: dbl.foo(1, nil, "other") |
| #<Double (anonymous)> received :foo with unexpected arguments |
| expected: (1, anything, /bar/) |
| got: (1, nil, "other") |

キーワード引数の使用

次の内容で "keyword_example_spec.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 examples, 1 failure                                                               |
| |
| Failure/Error: dbl.foo(bar: "incorrect") |
| #<InstanceDouble(WithKeywords) (anonymous)> received :foo with unexpected arguments |
| expected: ({:bar=>"baz"}) |
| got: ({:bar=>"incorrect"}) |

ハッシュとキーワード引数を区別する Rubies でのキーワード引数の使用

次の内容で "keyword_example_spec.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 example, 1 failure                                                                |
| |
| Failure/Error: dbl.foo({bar: "also incorrect"}) |
| #<InstanceDouble(WithKeywords) (anonymous)> received :foo with unexpected arguments |
| expected: ({:bar=>"baz"}) (keyword arguments) |
| got: ({:bar=>"also incorrect"}) (options hash) |

RSpec マッチャの使用

次の内容で "rspec_matcher_spec.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 examples, 1 failure                                         |
| |
| Failure/Error: dbl.foo([1, 3]) |
| #<Double (anonymous)> received :foo with unexpected arguments |
| expected: (a collection containing exactly 1 and 2) |
| got: ([1, 3]) |

カスタムマッチャの使用

次の内容で "custom_matcher_spec.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 examples, 1 failure                                         |
| |
| Failure/Error: dbl.foo(13) |
| #<Double (anonymous)> received :foo with unexpected arguments |
| expected: (a multiple of 3) |
| got: (13) |

引数に基づいて異なる応答を返す

次の内容で "responding_differently_spec.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 を実行すると、

すべての例がパスするはずです。