Unit tests generates "RuntimeError: Working outside of application context." with Mock 4.0.0

Viewed 907

After upgrading from Mock 3.0.5 to 4.0.0, my unit tests fail. I'm guessing patch is no longer working on flask.g but I haven't been able to find a workaround.

from mock import patch

import flask


def some_function():
    flask.g.somevariable = True
    return flask.g.somevariable


@patch('flask.g')
def test_some_function(mock_flask_global):
    assert some_function()

Output:

name = 'g'

    def _lookup_app_object(name):
        top = _app_ctx_stack.top
        if top is None:
>           raise RuntimeError(_app_ctx_err_msg)
E           RuntimeError: Working outside of application context.
E           
E           This typically means that you attempted to use functionality that needed
E           to interface with the current application object in some way. To solve
E           this, set up an application context with app.app_context().  See the
E           documentation for more information.

venv/lib/python3.6/site-packages/flask/globals.py:45: RuntimeError
========================================================================================================== short test summary info ===========================================================================================================
FAILED temp_test.py::test_some_function - RuntimeError: Working outside of application context.

This worked properly in mock 3.0.5

1 Answers

Neither the python devs or the flask devs take credit for this being a bug. Starting in python 3.8 with unittest.mock and with mock version 4.0.0 (they are the same), it checks to see if the attribute you are patching exists first. It's supposed to return the attribute or raise an AttributeError. Flask raises a RuntimeError, thus breaking the expected logic. On a side note, the Flask developers suggested not patching flask.g at all since its just a proxy to flask.globals.

Ultimately I was storing the DB connection in flask.g.db and wanted to patch that. My solution was to pass the database connection into the resource at construction and to not use flask.g outside of my before_request and teardown_request calls. For few cases where I do need to patch it, I just need the application context setup correctly.

Related