Skip to main content

diffable_block_expectations.md

🎯 Leveraging diffable and Block Expectations for Rich Output​

For assertions that involve large objects or side effects, combining diffable and supports_block_expectations in custom matchers enhances clarity by providing inline diffs and capturing exceptions. This technique gives you granular control over failure output and allows matchers to wrap code blocks for complex state changes.

# spec/support/matchers/change_database_record.rb
RSpec::Matchers.define :change_database_record do |model_class, id|
supports_block_expectations
diffable

match do |block|
@record_before = model_class.find(id).attributes
block.call
@record_after = model_class.find(id).attributes
@record_before != @record_after
end

failure_message do |block|
"expected block to change #{model_class}##{id} attributes, but it didn't.\n" +
"Before: #{@record_before.inspect}\nAfter: #{@record_after.inspect}"
end
end

# Usage in a spec:
expect { user.update!(name: 'New') }.to change_database_record(User, user.id)