2

I'm trying to write a matcher which transforms object to a Hash before comparing to the expected value (let say that I want to compare 2 hashes without caring about the fact that keys are strings or symbols).

I can easily define a matcher doing this

RSpec::Matchers.define :my_matcher do |content|
    match { |to_match| my_hash_conversion(to_match) == my_hash_conversion(content)
    diffable
end

I add diffable so rspec displays the diff of the two objects when they don't match. However I want to display the diff of the converted objects not the the diff of the original object ?

I saw they are somewhere in Rspec a Differ class and a diff_with_hash function, but I have no idea how to use it (as it's not really documented).

mb14
  • 22,276
  • 7
  • 60
  • 102
  • Can you add a conditional to the inner block to print out if not matching? As for printing out the hash, it may not actually be as useful as the original due to RSpec not distinguishing between Hash and OrderedHash in the printing as detailed here http://stackoverflow.com/questions/4728805/does-an-rspec2-matcher-for-matching-hashes-exist. – peakxu Sep 23 '12 at 11:48

2 Answers2

0

For RSpec3, you can use the Diff class directly.

RSpec::Matchers.define :my_matcher do |expected|
  expected_hash = my_hash_conversion(expected)
  match do |actual|
    actual_hash = my_hash_conversion(actual)
    expected_hash == actual_hash
  end

  failure_message do |actual|
    actual_hash = my_hash_conversion(actual)
    "expect #{expected_hash} to match #{actual_hash}" + 
      RSpec::Support::Differ.new.diff(actual_hash, expected_hash)
  end
end

Note: RSpec::Support says it's not supposed to be used directly.

Bibek Shrestha
  • 32,848
  • 7
  • 31
  • 34
-1

Use failure_message_for_should block :-

failure_message_for_should do |actual|
  "expected: #{expected} \n     got: #{actual}"
end

Then .to_hash what you need to see.

Ian Vaughan
  • 20,211
  • 13
  • 59
  • 79
  • Thanks but that doesn't help question is not how to write my own failure message, but how to reuse the rspec one. Rspec does actually a good diff, but not on the object I want. – mb14 Nov 07 '12 at 12:01