patching while testing flask app causes AssertionError: View function mapping is overwriting an existing endpoint function

时间:2018-09-18 20:27:28

标签: python unit-testing flask

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.

0 个答案:

没有答案