I am trying to write tests for a Flask app.
Currently I have a test that looks like this in a file called test.py.
import mock
from test_helpers import mock_volume_views_setup
class UserTest(unittest.TestCase):
def setUp():
<some set up>
def tearDown():
<some tear down>
@mock.patch('brain_db.views.volume_views_setup')
def test_labeled_scan(self, mock_volume_views_setup):
# test that if path to atlas exists in the container,
self.register_and_commit_user()
self.login_profile_consent()
self.upload('static/test.nii.gz', 1, '04/04/2008', 'GE', '1.5T')
rv = self.app.get('/label_view/1', follow_redirects=True)
response = str(rv.data)
assert "MRI not labeled yet" not in response
test.py lives a top level directory, flask_brain_db.
In flask_brain_db/brain_db/views.py lives the route I'm trying to test. A highly simplified version:
from brain_db_helpers import volume_views_setup
@app.route('/surface_test')
def surface_test():
return render_template('brain_db/surf_view.html')
@app.route('/label_view/<int:scan_number>')
@login_required
def label_view(scan_number):
a, b, c, d = volume_views_setup(scan_number, resource_type='atlas')
if os.path.exists(a):
return render_template('brain_db/scan_view.html')
When I try to run my test, I get
FAIL: test_labeled_scan (test.UserTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1297, in patched
arg = patching.__enter__()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1353, in __enter__
self.target = self.getter()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1523, in <lambda>
getter = lambda: _importer(target)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1210, in _importer
thing = _dot_lookup(thing, comp, import_path)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1199, in _dot_lookup
__import__(import_path)
File "/usr/src/app/flask_brain_db/brain_db/views.py", line 36, in <module>
@app.route('/surface_test')
File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1250, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 66, in wrapper_func
return f(self, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1221, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: surface_test
I understand what this error is trying to communicate. Somehow my patch decorator is, in an import, re-executing code that defines the routes in views.py, leading to the error. (The error doesn't appear without the patch decorator and mock function). But I don't understand why, or how I am supposed to patch my helper method. I have really struggled with understanding the correct way to refer to the method that needs patching, but looking at this question for example I think I'm doing it right.