When testing the outcome of nested rollbacks, we explicitly told a class to receive(:end!).and_raise(ActiveRecord::RecordNotSaved)
to emulate a deep failure in our transactions.
While testing, RSpec would raise this error during the test causing a test failure.
To remedy this we added a rescue
and raise
to the parent method and all was fine with the world.
def update_current_thing!(thing)
transaction do
other_things.each(&:end!)
end
rescue
raise ActiveRecord::Rollback
end
However, when looking at this code, and another similar instance of it, we thought that Rails should really handle this for us. Queue the refactor 🚧.
First, we removed the smelly code and saw our test suite fail again 🤔. Enter the investigation phase.
The investigation started as no more than a hunch that this code should work as expected, without the explicit raise
, as per the Rails documentation
The investigation led to a blog post discussing the very same issue, with the solution of wrapping the expectation in a suppress
block.
Suppressing the errors stops RSpec from failing due to the error and instead allows the rest of the test to be executed.
suppress(ActiveRecord::RecordNotSaved) do
thing.update_current_thing!(other_thing)
end
expect(thing.current_thing).to eq(other_thing)