I have an array of hashes and I'm trying to assert that the array has exactly a certain number of hashes in a certain order that have a certain key.
So let's say I have an array of fruits.
fruits = [
{ name: 'apple', count: 3 },
{ name: 'orange', count: 14 },
{ name: 'strawberry', count: 7 },
]
When I use the eq
matcher with hash_including
(or include
which is its alias), the assertion fails.
# fails :(
expect(fruits).to eq([
hash_including(name: 'apple'),
hash_including(name: 'orange'),
hash_including(name: 'strawberry'),
])
It's weird that this doesn't work and I've always found a way around it and moved on, but it's been bothering me for a while, so I decided to post about it this time.
Obviously this works but I like the other syntax because that's kinda the point of these matchers: so I don't have to transform my data structures by hand and have more readable specs.
fruit_names = fruits.map { |h| h.fetch(:name) }
expect(fruit_names).to eq(['apple', 'orange', 'strawberry'])
contain_exactly
and include
work but I care about the exact size of the array and the order of elements, which they fail to assert.
# passes but doesn't assert the size of the array or the order of elements
expect(fruits).include(
hash_including(name: 'apple'),
hash_including(name: 'orange'),
hash_including(name: 'strawberry'),
)
# passes but doesn't assert the exact order of elements
expect(fruits).contain_exactly(
hash_including(name: 'apple'),
hash_including(name: 'orange'),
hash_including(name: 'strawberry'),
)
Looks like you just need to use match
fruits = [
{ name: 'apple', count: 3 },
{ name: 'orange', count: 14 },
{ name: 'strawberry', count: 7 },
]
expect(fruits).to match([
include(name: 'apple'),
include(name: 'orange'),
include(name: 'strawberry'),
])
This test will fail if some array element is missing or extra
This test will fail if some of hashes doesn't include specified key-value pair
This test will fail in case of wrong array elements order