25

Consider the following RSpec snippet:

it "should match" do
  {:a => 1, :b => 2}.should =~ {"a" => 1, "b" => 2}
end

This test fails because one hash uses symbols for keys and the other uses strings for keys. In my case, one hash is a parsed JSON object, the other is the hash that created the object. I'd like them to compare as equal.

Before I go writing my own matcher or coercing both hashes to have string keys, is there a matcher or technique that handles this (common) case?

fearless_fool
  • 33,645
  • 23
  • 135
  • 217

4 Answers4

26

You could do:

it "should match" do
    {:a => 1, :b => 2}.stringify_keys.should =~ {"a" => 1, "b" => 2}
end
Shailen Tuli
  • 13,815
  • 5
  • 40
  • 51
18

Assuming you have access to Rails's ActiveSupport. You can leverage with_indifferent_access to match both hashes. Below is an example with the hashrocket Ruby syntax and the Rspec expect syntax:

it 'matches two hashes' do
  hash_1 = {a: 1, b: 2}.with_indifferent_access
  hash_2 = {'a' => 1, 'b' => 2}
  expect(hash_1).to match(hash_2)
end

Note: make sure to use with_indifferent_access on the hash with the symbol keys

Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
Yacc
  • 1,068
  • 11
  • 16
1

The simplest way would be to write it so that it'd match the thing you're getting, like putting strings if you get strings, or putting symbols if you get symbols.

If you can't do that, what I'd do would be something like :

it "should match" do
  {:a => 1}.with_indifferent_access.should =~ {'a' => 1}.with_indifferent_access
end
mat
  • 12,943
  • 5
  • 39
  • 44
0

i've never heard of one, but you could have a look at active_supports HashWithIndifferentAccess that solves this problem within rails: http://apidock.com/rails/ActiveSupport/HashWithIndifferentAccess

phoet
  • 18,688
  • 4
  • 46
  • 74