mercredi 9 décembre 2020

How to test rescue logic when re-raising error afterwards Rails/Rspec?

I have the following code which rescues an exception, updates some status attributes on a model, and then re-raises the error to allow it to bubble up to the calling class.

foo.rb

class Foo
  ...
  ...

  def bar
    External::Service.new().bar # this raises ArgumentError (for example)
  rescue ArgumentError => e
    message = 'Foo: Wrong id passed`
    report.update!(status: 'error')
    raise e
  end
end

In my specs I want to test that it updates the status, and also re-raises the error. Re-raising the error is fine to test, however I can't figure out a way to test updating message attribute as rspec just says an error was raised.

foo_spec.rb

RSpec.describe Foo do
  describe '#bar' do
    subject(:call_bar) { described_class.new().bar }

    let(:report) { create(:report, status: 'generating') }

    before do
      allow(External::Service).to receive(:new)
        .and_raise ArguementError
    end
  
    it 're-raises the error' do 
      expect { call_bar }.to raise_error(ArgumentError) # works fine
    end

    it 'updates status' do
      expect { call_bar }.to change(report, :status) # does not work as rspec just sees error
    end
  end
end

I've tried something along the lines of this as well but the issue is that the rescue in the spec is called instead of the one in the code being tested when the error is first raised. The spec will pass but no attributes will be updated so it's a false positive.

it 'updates status' do
  call_bar
rescue
  expect(report.reload.status).to eq 'error'
end

Aucun commentaire:

Enregistrer un commentaire