0

I've got a method as follows:

 if response.fetch('ok')
    response.fetch(response_key) { [] }
  elsif response.fetch('error') == 'token_revoked'
    ErrorReporter.increment('access_revoked', source: { account_id: account_id }, sporadic: true)
    fail(RemoteService::AccessRevoked, 'Our access to your account was revoked, please re-authorize.')
  else
    ErrorReporter.increment(
      'bad_request',
      source: {
        account_id: account_id
        error: response.fetch('error')
      },
      sporadic: true
    )
    fail(RemoteService::InvalidRequest, 'Something went wrong communicating with the remote service, please try again')
  end

And I'm trying to test the scenario when the request returns with the token_revoked error. I'd like to ensure the test specifies that in this scenario, that we report the error to our ErrorReporting service.

So, my spec looks like this:

it 'records the failure with our error reporting service' do
  expect(ErrorReporter).to receive(:increment).with(
    'bad_request',
     source: {
       account_id:  1
     },
     sporadic: true
   )

   available_channels.fetch
end

However, this spec always fails, because after the call is made to the ErrorReporter, the code immediately calls fail which makes my spec fail. Does anyone have any idea how I can verify that the call to my error reporter is made while handling the inevitable exception that I know the code is now going to throw?

Holger Just
  • 52,918
  • 14
  • 115
  • 123
TheDelChop
  • 7,938
  • 4
  • 48
  • 70
  • Does this help? [how-to-test-exception-raising-in-rails-rspec](https://stackoverflow.com/questions/22141601/how-to-test-exception-raising-in-rails-rspec) – max pleaner Dec 05 '17 at 21:16
  • No, that doesn't help, the spec after that handles the fact that I expect an exception to be thrown, here I'm trying to assert that we send the error to our service _before_ the exception is thrown. – TheDelChop Dec 05 '17 at 21:25
  • 1
    Just wrap the call to `available_channels.fetch` in a `begin ... rescue RemoteService::InvalidRequest` block. – Stefan Dec 05 '17 at 21:31
  • @Stefan beat me to it – engineersmnky Dec 05 '17 at 21:32

2 Answers2

1

You can expect errors to be raised in code. In order for the exception to be caught by RSpec, you need to use a block as follows:

it 'records the failure with our error reporting service' do
  expect(ErrorReporter).to receive(:increment).with(
    'bad_request',
    source: {
      account_id:  1
    },
    sporadic: true
  )

  expect { available_channels.fetch }
    .to raise_error RemoteService::InvalidRequest
end
Holger Just
  • 52,918
  • 14
  • 115
  • 123
  • Yeah this is what I also concluded, thank you for confirming this approach might be the best way to handle it. – TheDelChop Dec 05 '17 at 21:57
-2

The exception causes your example to fail because it is not rescued. To prevent the error, you can wrap the method call in a begin ... rescue block:

it 'records the failure with our error reporting service' do
  expect(ErrorReporter).to receive(:increment).with(
    'bad_request',
     source: {
       account_id:  1
     },
     sporadic: true
   )

   begin
     available_channels.fetch
   rescue => RemoteService::InvalidRequest
     # would cause the example to fail
   end
end

In another example, you should also expect the error to be raised.

Stefan
  • 109,145
  • 14
  • 143
  • 218