Failing RSpec have_attributes with arguments matchers
Why when using have_attributes with multiple argument matchers and only one is a failure, RSpecs fails all the rest of matchers ?
Why when using have_attributes with multiple argument matchers and only one is a failure, RSpec fails all the rest of matchers ?
Code example#
require 'rspec'
Customer = Struct.new(:id, :name)
RSpec.describe 'fail' do
subject { Customer.new(123, 'Some Name') }
it 'fails' do
expect(subject).to have_attributes(
id: kind_of(String),
name: kind_of(String)
)
end
endFailure#

Although only the id is invalid we see both :name & :id as failed.
Why?#
When it’s time for RSpec to output the failure results it diffs the expected values with the given. In order to diff object rspecs uses RSpec::Support::Differ that turns them into strings by inspecting them.
Since we use the RSpec::Mocks::ArgumentMatchers::KindOf argument matcher RSpec matches it with the
RSpec::Support::ObjectFormatter::DescribableMatcherInspector and then we get the kind of String.
You can replicate it by running:
RSpec::Support::ObjectFormatter::DescribableMatcherInspector.new(
RSpec::Mocks::ArgumentMatchers::KindOf.new(String)
).inspectWhen it’s time to compare the diffs we compare the kind of String with Some Name and we end up with the red error output although the matcher did not fail for that particular attribute.
Here is a Github issue for that.