7

I have unittested all the methods from my flask-restful API module. Now I want to test get method by actually making the API call. I expect error 400 from this test.

My resource class

class Response(Resource):

    @marshal_with(response_params_get_responses_on_job)
    def get(self, filter_name=None):
        try:
            response = self.process_get_request(filter_name)
            if not response['users']:
                raise MyValidationError("No data found")
            return response
        except MyValidationError as err:
            abort(404, message=err)
        except ValueError as mistake:
            abort(400, message=mistake)

My Unittest

# TODO - Failing!
@mock.patch('application.resources.response.Response.process_get_request', autospec=True)
def test_get_400(self, process_get_request_mock):
    process_get_request_mock.side_effect = ValueError("some error")
    app = Flask(__name__)
    app.debug = True
    api = Api(app, prefix='/api/v2')
    api.add_resource(Response, '/user/responses', endpoint='job_responses')
    api.init_app(app)
    with app.test_client() as client:
        resp = client.get('/api/v2/user/responses',
                          environ_base={'HTTP_USER_AGENT': 'Chrome'},
                      headers={'Content-type': 'application/json'})
        self.assertEqual(resp.status_code, 400)

My test fails because the response I get is error 500

AssertionError: 500 != 400

Stacktrace

Failure
Traceback (most recent call last):
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/mock.py", line 1201, in patched
return func(*args, **keywargs)
File "/home/hussain/workspace/my-app/tests/unittests/test_Response.py", line 38, in test_get_400
headers={'Content-type': 'application/json'})
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/werkzeug/test.py", line 774, in get
return self.open(*args, **kw)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask/testing.py", line 108, in open
follow_redirects=follow_redirects)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/werkzeug/test.py", line 742, in open
response = self.run_wsgi_app(environ, buffered=buffered)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/werkzeug/test.py", line 659, in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/werkzeug/test.py", line 867, in run_wsgi_app
app_rv = app(environ, start_response)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_cors/extension.py", line 110, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 267, in error_router
return self.handle_error(e)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 267, in error_router
return self.handle_error(e)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_cors/extension.py", line 110, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
File "/home/hussain/workspace/venv/local/lib/python2.7/site-packages/flask/app.py", line 1363, in handle_user_exception
assert exc_value is e
AssertionError

By putting a debug point in get method, I see that the execution goes till abort(400, message=mistake).

Then what is going on? Why does my test fail?

Hussain
  • 5,057
  • 6
  • 45
  • 71
  • I'm not a Flask expert but AFAIK you use a wrong `abort()` syntax. If you print `resp` content maybe you will find a `TypeError` logged in. Take a look to http://stackoverflow.com/a/21301229/4101725 if you want to know how to use it. But the first shot could be use just `abort(400)` or `abort(404)`. Anyway you should be happy: your test found a insidious bug in error handler :) – Michele d'Amico Sep 22 '15 at 20:02
  • ... just one more thing... Let me know if it works that I will file an answer. – Michele d'Amico Sep 22 '15 at 20:58
  • Hey. You are right! There is no issue in the syntax of abort, It's what I was passing to it. The `message` kwarg that I pass to `abort` should be a string. So I have changed it to `abort(404, message=err.message)`. I need to keep this in mind. Thanks for the help. – Hussain Sep 23 '15 at 06:44
  • Ok, somebody should write an answer: we cannot leave the answer in comments. Do you write it or I should do it? – Michele d'Amico Sep 23 '15 at 06:50
  • Okay. I'll write it. – Hussain Sep 23 '15 at 07:53

1 Answers1

4

For all the time I assumed the issue was with my unit test. I was wrong!

The issue was in my code. And as Michele said my test has found it.

The message kwarg in abort method is expected to be a string, and instead I was passing it the exception object. So I was getting an exception on the abort line.

So I corrected it

abort(400, message=mistake.message)

Alternatively I can also write

abort(400, message=str(mistake))

Now my test is passing.

Hussain
  • 5,057
  • 6
  • 45
  • 71