I would really like to use the hash_including matcher on HTTP Headers:
stub_request(:post, 'https://test.host').
with(
body: expected_body
headers: hash_including(expected_headers))
However I am getting this error:
Failure/Error: stub_request(:post, 'https://test.host').
NoMethodError:
undefined method `map' for #<RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher:0x007fc81488e530>
I suppose it is raised on this line
:+1: had the same issue. Ended up with this workaround:
assert_requested(:get, @url) do |req|
req.headers["Foo"] == "Bar"
end
Will look into fixing this in Webmock next, seems a bit tricky.
You could try
stub_request(:post, 'https://test.host').
to_return(
body: expected_body
headers: hash_including(expected_headers))
I'm having the same problem:
auth = ActionController::HttpAuthentication::Basic.encode_credentials('yah', 'yah')
headers = { :authorization => auth }
WebMock.stub_request(:any, /\Ahttp:\/\/localhost:3000\/.*\/newsletter\Z/).with(:headers => hash_including(headers)).to_return(:status => 200, :body => '<html></html>')
Headers are matched by default if request headers include stub headers. It's enough if stub headers are a subset of request headers. There is no need to use hash_including
.
as described in README, request is matched if "request headers match stubbed request headers, or stubbed request headers match a subset of request headers, or stubbed request headers are not specified"
Thanks @bblimke That worked for me. I had copied the body example and tried to modify it.
:+1:
Headers are matched by default if request headers include stub headers. It's enough if stub headers are a subset of request headers. There is no need to use
hash_including
.
Unfortunately this doesn't seem to be the case if you use have_requested
.
expect(WebMock).to have_requested(:get, ...").
with(:headers => { 'Accept' => 'application/json', 'Foo' => 'Bar' })
doesn't pass if other than Accept
and Foo
you have other headers.
@weppos It matches if there are more headers in the request than expected. Please have a look here:
https://github.com/bblimke/webmock/blob/master/spec/acceptance/shared/request_expectations.rb#L380-L388
Please provide a failing code sample.
You can see an example here.
https://github.com/aetrion/dnsimple-ruby/blob/102ce131bebfd9be2adb0b5c296893e2b9e94886/spec/dnsimple/user_spec.rb#L43-L45
If I use
it "builds the correct request" do
described_class.two_factor_exchange_token(otp_token)
expect(WebMock).to have_requested(:get, "https://#{CONFIG['username']}:#{CONFIG['password']}@#{CONFIG['host']}/v1/user").
# workaround for https://github.com/bblimke/webmock/issues/276
with(headers: hash_including('X-Dnsimple-Otp' => otp_token))
end
the test fails with
NoMethodError:
undefined method `map' for #<RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher:0x007fa6bc15a9e0>
# /Users/weppos/.rvm/gems/ruby-2.1.5@dnsimple-ruby/gems/webmock-1.20.4/lib/webmock/util/headers.rb:9:in `normalize_headers'
# /Users/weppos/.rvm/gems/ruby-2.1.5@dnsimple-ruby/gems/webmock-1.20.4/lib/webmock/request_pattern.rb:292:in `initialize'
# /Users/weppos/.rvm/gems/ruby-2.1.5@dnsimple-ruby/gems/webmock-1.20.4/lib/webmock/request_pattern.rb:55:in `new'
# /Users/weppos/.rvm/gems/ruby-2.1.5@dnsimple-ruby/gems/webmock-1.20.4/lib/webmock/request_pattern.rb:55:in `assign_options'
# /Users/weppos/.rvm/gems/ruby-2.1.5@dnsimple-ruby/gems/webmock-1.20.4/lib/webmock/request_pattern.rb:24:in `with'
# /Users/weppos/.rvm/gems/ruby-2.1.5@dnsimple-ruby/gems/webmock-1.20.4/lib/webmock/rspec/matchers/webmock_matcher.rb:20:in `with'
@weppos There is no need to use hash_including. Headers are matched if expected headers are a subset of received headers.
@bblimke I made the change... and it worked! I swear it didn't work in the old days. :(
@weppos I'm glad it works now :)
weirdly, I am having the same problem as the OP :/
When I omit hash_including Webmocks complains that the headers were not as expected.
Nevermind. It was user error :) ... I had a typo in my headers. Confirming that it works alright without using hash_including
For anyone that landed here: https://stackoverflow.com/a/49360133/2724342
Web mock header and params need to be an exact match. Most mismatched is from symbol/string keys.
I understand that header matching only occurs on the subset of headers passed into the with(headers: ...subset...)
method and this matches most of the hash_including
functionality. It seems that hash_including
can also match on keys being present (without values being specified, ie hash_including(:key1, :key2)
). Is there a way to do that in a with(headers: KEYS_THAT_MUST_APPEAR)
statement?
And how about hash_excluding
? I'd like to test that my headers didn't not include any Authorization key.
I think my use case is the inverse of that - verify that headers include an Authorization key but I don't care what it is specifically (in fact I might not even be able to know a priori).
@jdalt I wasn't really offering a solution to your problem but more adding another use case where it would help to be able to use matchers
Most helpful comment
Headers are matched by default if request headers include stub headers. It's enough if stub headers are a subset of request headers. There is no need to use
hash_including
.