Pistos
Pistos

Reputation: 23792

rspec: multiple expectations about expected method arguments

Is there a way to get a handle on the arguments passed to the test subject, and then test multiple distinct expectations on the arguments? Something like this:

expect(foo).to receive(:bar)

subject.method_under_test

expect(args_passed_to_foo).to be hash_including(key1: "some value")
expect(args_passed_to_foo).to be hash_including(key2: /some regexp/)
expect(args_passed_to_foo.keys).not_to include(:key3)
expect(some_method(args_passed_to_foo[:key4])).to be > SOME_CONST

The only way that I know to sort of do the above is something like:

expect(foo).to receive(:bar).with(
  # ........
)

subject.method_under_test

but that can't really handle the most complex cases, and it also is terribly unwieldly, and you are testing many things with one expect, which doesn't seem right.

Upvotes: 1

Views: 2043

Answers (1)

Fito von Zastrow
Fito von Zastrow

Reputation: 760

Yes, the way to get a handle on the arguments passed to a test subject is:

before do
  allow(foo).to receive(:bar)
end

it 'does something' do
  subject.method_under_test

  expect(foo).to have_received(:bar) do |args_passed_to_foo|
    expect(args_passed_to_foo).to be hash_including(key1: "some value")
    expect(args_passed_to_foo).to be hash_including(key2: /some regexp/)
    expect(args_passed_to_foo.keys).not_to include(:key3)
    expect(some_method(args_passed_to_foo[:key4])).to be > SOME_CONST    
  end
end

RSpec allows you to pass a block after a have_received expectation. The block will be yielded the arguments passed to the actual call.

Upvotes: 4

Related Questions