aarona
aarona

Reputation: 37303

RSpec: hash_including not working as I expected

Consider the following json response:

{
  "data": {
    "someFunction": null
  },
  "errors": [
    {
      "message": "Email was already confirmed, please try signing in",
      "locations": [
        {
          "line": 9,
          "column": 2
        }
      ],
      "path": [
        "someFunction"
      ],
      "extensions": {
        "code": "USER_ERROR"
      }
    }
  ]
}

Now in a test I'm expecting the following to be a valid response:

expect(json_response[:errors]).to contain_exactly(
  hash_including(
    message: "Email was already confirmed, please try signing in.",
    extensions: { code: 'USER_ERROR' }
  )
)

The above response should be valid except that my tests are saying that it's not:

expected collection contained:  [hash_including(:message=>"Email was already confirmed, please try signing in.", :extensions=>{:code=>"USER_ERROR"})]
actual collection contained:    [{:extensions=>{:code=>"USER_ERROR"}, :locations=>[{:column=>9, :line=>2}], :message=>"Email was already confirmed, please try signing in", :path=>["someFunction"]}]
the missing elements were:      [hash_including(:message=>"Email was already confirmed, please try signing in.", :extensions=>{:code=>"USER_ERROR"})]
the extra elements were:        [{:extensions=>{:code=>"USER_ERROR"}, :locations=>[{:column=>9, :line=>2}], :message=>"Email was already confirmed, please try signing in", :path=>["someFunction"]}]

What am I doing wrong here?

Upvotes: 0

Views: 3750

Answers (2)

Horacio
Horacio

Reputation: 2965

The problem is you are doing so much in a test (and you don't have to nest matchers)

Because contain_exactly matcher will return true or error.

So a suggestion try not to do complex test and try to avoid more than one expectations on the same test

  it 'includes data and errors' do
    expect(json_response.keys).to contain_exactly(:data, :errors)
  end

  it 'Email error has message' do
    expect(json_response[:errors][0][:message]).to eq 'Email was already confirmed, please try signing in'
  end

  it 'Email error has code' do
    expect(json_response[:errors][0][:extensions]).to eql(code: 'USER_ERROR')
  end

It should work

Upvotes: 1

aarona
aarona

Reputation: 37303

Using one of Horacio's tests, I was able to determine I was expecting a period. Dismissing a core function of Rspec and not using it is not the solution that I wanted. However, this was a learning experience for myself and hopefully anyone else who comes across this question wondering what they did wrong, they'll see a simple mistake from pairing contain_exactly and hash_including together may cause your error output to deceive you into thinking you're doing something really wrong when in actuality, you probably made a simple mistake.

This sanity check:

expect(json_response[:errors][0][:message]).to eq 'Email was already confirmed, please try signing in'

Resulted in me finding my simple mistake:

 expected: "Email was already confirmed, please try signing in."
      got: "Email was already confirmed, please try signing in"

Upvotes: 0

Related Questions