cjauvin
cjauvin

Reputation: 3693

Flask handle_exception doesn't work with test_request_context

I noticed that app.handle_exception doesn't seem to be called when the exception occurs with an app.test_request_context:

from flask import *

app = Flask(__name__)
app.handle_exception = lambda e: 'exception!'

@app.route('/foo')
def foo():
    x = 1 / 0
    return 'ok'

if __name__ == '__main__':
    #app.run(port=81) # handle_exception works here
    with app.test_request_context('/foo'):
        print app.dispatch_request() # but not here

Is this the expected behavior?

Upvotes: 1

Views: 2068

Answers (2)

Mark Hildreth
Mark Hildreth

Reputation: 43071

Not sure if this is what you're after: according to the docs for dispatch_request:

Does the request dispatching. Matches the URL and returns the return value of the view or error handler. This does not have to be a response object. In order to convert the return value to a proper response object, call make_response().

Changed in version 0.7: This no longer does the exception handling, this code was moved to the new full_dispatch_request().

So, perhaps replace...

with app.test_request_context('/foo'):
    print app.dispatch_request() # but not here

...with...

with app.test_request_context('/foo'):
    print app.full_dispatch_request() # Hopefully this works now :)

Upvotes: 1

Tigra
Tigra

Reputation: 2631

You can easily override this behaviour and force handling exceptions with same handler.

def run_test(path=None,check_func=None,*args,**kwargs):
    with app.test_request_context(path,*args,**kwargs):
        try:
            data=app.dispatch_request() 
            if check_func is not None:
                 check_func()
            else:
                print data
        except Exception as e:
            print app.handle_exception(e)

run_test('/')
run_test('/other')

def current_test(data):
     assert 'has some content' in data
run_test('/should_be_checked',check_func=current_test)

And another word.

Your approach does not work because you just do not use that part of Flask, which actually catches Exception. You are calling context directly.

Quote from documentation:

If you look into how the Flask WSGI application internally works, you will find a piece of code that looks very much like this:

def wsgi_app(self, environ):
    with self.request_context(environ):
        try:
            response = self.full_dispatch_request()
        except Exception, e:
            response = self.make_response(self.handle_exception(e))
        return response(environ, start_response)

But! Following would be the correct way to do it, since all Flask methods on every level will be called in appropriate way:

with app.test_request_context():
    with app.test_client() as client:
        resp = client.get('/')
        #and if you need content of response: print resp.data

---

Upvotes: 1

Related Questions