Reputation: 63
I've got a Flask app module (app.py
) which looks like this
# imports
...
from flask import Flask, request, Response
...
# module-level vars, including `logger` and `APP`
...
logger = None
APP = None
...
def init():
"""
Initialisation of app resources, including `logger`
"""
...
APP = Flask(__name__)
...
logger = logging.getLogger()
...
...
try:
init()
except Exception as e:
logger.error(str(e))
@APP.route('/healthcheck', methods=['GET'])
def healthcheck():
"""
Healthcheck endpoint - just returns OK if the app
initialised OK.
"""
return 'OK'
@APP.route('/get_keys', method=['POST'])
def get_keys():
"""
Main endpoint - accepts a POST request from a client
containing either a CSV or JSON payload defining a set
of geographic locations, and then returns some "keys"
for these.
"""
try:
logger.info('Extracting payload')
# extract payload
logger.info('Processing for keys')
# do some stuff
...
...
except Exception as e:
logger.error("Error: {}.".format(str(e)))
# return response
I've got unit tests for the Flask app defined in a module AppTests
in the tests
subpackage.
# general imports including `unittest` etc.
# import app module as `app`
class AppTests(unittest.TestCase):
"""
Flask app tests
"""
@classmethod
def setUpClass(self):
app.APP.config['TESTING'] = True
app.APP.config['DEBUG'] = False
self.app = app.APP.test_client()
# define other resources needed for `self.app`
def test_healthcheck(self):
res = self.app.get(path='/healthcheck')
self.assertEqual(res.status_code, 200)
def test_get_keys__csv(self):
# define sample csv data in `data` variable
headers = {
'Accept-Encoding': 'identity,deflate,gzip,compress',
'Content-Type': 'text/csv; charset=utf-8',
'Content-Length': len(data)
}
res = self.app.post(path='/get_keys', headers=headers.items(), data=data)
self.assertEqual(res.status_code, 200)
The test for the healthcheck
endpoint passes but the test for the get_keys
endpoint fails.
$ python -m unittest -v AppTests.AppTests.test_get_keys__csv
test_get_keys__csv (AppTests.AppTests) ...
ERROR
======================================================================
ERROR: test_get_keys__csv (AppTests.AppTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "AppTests.py", line 105, in test_get_keys__csv
res = self.app.post(path='/get_keys', headers=headers.items(), data=data)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 801, in post
return self.open(*args, **kw)
File "/path/to/venv/lib/python2.7/site-packages/flask/testing.py", line 127, in open
follow_redirects=follow_redirects)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 764, in open
response = self.run_wsgi_app(environ, buffered=buffered)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 677, in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 884, in run_wsgi_app
app_rv = app(environ, start_response)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1994, in __call__
return self.wsgi_app(environ, start_response)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/path/to/app.py", line 205, in get_keys
logger.error("Error: {}.".format(str(e)))
AttributeError: 'NoneType' object has no attribute 'error'
----------------------------------------------------------------------
Ran 1 test in 0.036s
FAILED (errors=1)
It looks like the reference to the logger
object in the get_keys
endpoint in the app is null when I make the call to self.app.post('/get_keys, headers=headers.items(), data=data)
. Every call to logger.info
is generating an exception in the endpoint, which is caught and logged, and that's what I am seeing when I run the endpoint test.
Is there a way to mock this, or some how bypass the use of logger
from the tests module itself? I would rather not modify the endpoint method itself.
Upvotes: 3
Views: 2313
Reputation: 22994
You could potentially mock out the logging import when you run test_get_keys__csv()
.
from unittest.mock import patch
@patch('path.to.app.logging') # Mock the logging import
def test_get_keys__csv(self, mock_logging):
# define sample csv data in `data` variable
headers = {
'Accept-Encoding': 'identity,deflate,gzip,compress',
'Content-Type': 'text/csv; charset=utf-8',
'Content-Length': len(data)
}
res = self.app.post(path='/get_keys', headers=headers.items(), data=data)
self.assertEqual(res.status_code, 200)
If you're using Python 2, mock
is a separate install.
pip install mock
and then import with
from mock import patch
More info on mock: https://docs.python.org/3/library/unittest.mock.html
Upvotes: 2