0

I have an application that raises 404 Sinatra::NotFound errors on production when the route is missing.

However, the following test passes:

it 'should not raise error' do
  expect{ get '/unknown_path' }.to_not raise_error
end

Why don't 404 Sinatra::NotFound errors get raised in the test?

The following does raise the error and cause the test to fail:

get '/unknown_path' do
  raise 'error'
end

How to test for 404 Sinatra::NotFound errors?

B Seven
  • 44,484
  • 66
  • 240
  • 385

2 Answers2

2

The issue is that get /unknown_path' is not actually raising an error – it's only receiving a 404 request.

From Sinatra: README

The error handler is invoked any time an exception is raised from a route block or a filter. The exception object can be obtained from the sinatra.error Rack variable...

Your test is testing for an actual error (this is what raise_error does), while Sinatra is squashing the error – otherwise, every time someone 404'd the server would crash!

Check out the Sinatra testing guide for better direction on forming your tests. The basic idea is that using get ... in a test sets the last_response local variable, which can then be tested for equality, etc.

last_response has a status attribute, so (like was mentioned in another answer) you can just test to make sure that last_response.status equals 404.

Edit:

I wasn't really clear about this. In testing mode, the application does actually raise errors.

From Sinatra Settings

raise_errors raise exceptions (will stop application). Enabled by default when environment is set to "test", disabled otherwise.

So you don't actually want to raise just any error, but raise Sinatra::NotFound.new("Not found!") to raise the specific type of error. The Sinatra::NotFound error will trigger the 404 handler. Sinatra Error Handling

Community
  • 1
  • 1
acsmith
  • 1,466
  • 11
  • 16
  • I don't quite understand...what do you mean exception on production? – acsmith Aug 30 '13 at 04:02
  • I made a few changes, which will hopefully clear that up. You want to be sure to raise the right *type* of error, or else it'll just raise Exception by default. (uh, I think so anyway) – acsmith Aug 30 '13 at 04:09
  • 1
    I mean that we are using Honeybadger, and it is getting route not found errors. It is only supposed to catch exceptions. So the mystery is, in test it does not raise an error, but on production it does raise errors and send them to Honeybadger. – B Seven Aug 30 '13 at 14:29
  • Okay, so what happens when you replace `raise 'error'` with `404` (a shortcut for raising a `404` NotFound error), and change the test to look for the status of the last response rather than just see if an error was thrown? – acsmith Aug 30 '13 at 16:11
  • @BSeven did you ever figure out how to not send 404 errors to Honeybadger? – dentarg Sep 16 '13 at 16:03
  • @dentarg - No...it seems like this issue has to do with the 404 handler in Sinatra, Rack::Test and the Honeybadger gem. I didn't dig into them to figure out what is happening. – B Seven Sep 16 '13 at 20:07
1

Try this:

get '/unknown_path'
assert_equal last_response.status, 404
Cole Pilegard
  • 582
  • 2
  • 11