Complex Hash Expectations in RSpec

When spec-ing something that calls method which takes a set of nested hashes (as many Rails methods do), it may be tempting to use #hash_including: to test for only the values you care about. However #hash_including won’t work the way we might hope for nested hashes. Take the following (highly contrived) example:

If we run this we get a failure:

Clearly #hash_including was only intended to work with shallow hashes.

Instead, we can use a lesser-known feature of RSpec’s mock objects to test only the values we care about:

Here we’ve supplied a block to #should_receive. The block will be called when the mocked method is called, and will be passed whatever arguments the mocked method was called with. Inside we can use any kind of RSpec assertions we like.

Here’s the failure message if we supply :roast => :dark instead of :medium: