bblimke / webmock

Library for stubbing and setting expectations on HTTP requests in Ruby.
MIT License
3.96k stars 557 forks source link

Nested hash_including not working properly along with RSpec #900

Open jefgarzon opened 4 years ago

jefgarzon commented 4 years ago

When using hash_including expectations don't pass at least I tell it explicitly to use Webmock::API.hash_including.

Those two version should pass but first one don't.

fails.rb

require 'rspec'
require 'webmock/rspec'
require 'rest-client'

RSpec.describe 'hash_including' do

  it 'must passed' do

    url = 'http://test.com/resource'

    stub_request(:post, url)

    RestClient.post(url,
      {
        a: 1,
        b: {
          c: 3,
          d: 4
        }
      }.to_json,
      {
        content_type: :json
      }
    )

    expect(a_request(:post, url)
      .with(body: hash_including(
        a: 1,
        b: hash_including(c: 3)
      ))).to have_been_made
  end
end

pass.rb

require 'rspec'
require 'webmock/rspec'
require 'rest-client'

RSpec.describe 'hash_including error' do

  it 'must passed' do

    url = 'http://test.com/resource'

    stub_request(:post, url)

    RestClient.post(url,
      {
        a: 1,
        b: {
          c: 3,
          d: 4
        }
      }.to_json,
      {
        content_type: :json
      }
    )

    expect(a_request(:post, url)
      .with(body: hash_including(
        a: 1,
        b: WebMock::API.hash_including(c: 3)
      ))).to have_been_made
  end
end

Not sure if we must specify the hash_including version to use each time, but researching a little bit it looks like WebMock version is stringifying the keys of the expected partial hash but Rspec version don't, so the error occurs once the key-to-key comparison is being made and do to different type of the keys, the response body returns nil for all keys since it's being query with symbol instead of string.

webmock https://github.com/bblimke/webmock/blob/382d84ca586fc87755d5657616d7a492421ee11b/lib/webmock/matchers/hash_argument_matcher.rb#L5-L8

rspec https://github.com/rspec/rspec-mocks/blob/0a52e0a86b126b4bab94d277b2ad99a7492dc37d/lib/rspec/mocks/argument_matchers.rb#L178-L181

bblimke commented 4 years ago

@jefgarzon it's only when using nested hash_including right? I don't think nested hash_including has every been tested in WebMock

bblimke commented 4 years ago

WebMock's version of hash_including has ben developed to cover hash_including in other environments than Rspec. When RSpec is used, default RSpec's hash_including is supposed to be used. I guess the expected result is to have the first example pass. Perhaps the keys should be stringified as well, before passing the hash to RSpec matcher, though these would have to be stringified in the nested hash_including's as well, which is tricky.