I have a custom matcher that uses expects in it's match block (the code here is simplified)
RSpec::Matchers.define :have_foo_content do |expected|
match do |actual|
expect(actual).to contain_exactly(expected)
expect(actual.foo).to contain_exactly(expected.foo)
end
end
Normally the error message would look like this
expected collection contained: ["VLPpzkjahD"]
actual collection contained: ["yBzPmoRnSK"]
the missing elements were: ["VLPpzkjahD"]
the extra elements were: ["yBzPmoRnSK"]
But when using a custom matcher, it only prints this, and important debug information gets lost:
expected MyObject to have_foo_content "foobar"
So, is it possible to re-use a error message from the match block as a failure message? I know I can provide custom failure messages with
failure_message do |actual|
# ...
end
But I don't know how you could access the failure message the error above has raised.
You can rescue RSpec::Expectations::ExpectationNotMetError
in your match
to catch the failed expectation message:
match do |object|
begin
expect(object).to be_nil
rescue RSpec::Expectations::ExpectationNotMetError => e
@error = e
raise
end
end
failure_message do
<<~MESSAGE
Expected object to meet my custom matcher expectation but failed with error:
#{@error}
MESSAGE
end
Don't forget to re-raise in the rescue
, otherwise it won't work
There is no direct method available to yield original error, I would suggest you to write your own logic to generate similar message.
If you still want to use the existing method, there is a private method which you can call and it will return the default error message. You may need to set some instance variables expected_value
, actual_value
etc.
RSpec::Matchers::BuiltIn::ContainExactly.new(expected_value).failure_message
reference code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With