Christopher Will
Christopher Will

Reputation: 3064

Mocking current_app in Flask unit pytest

I want to unit test following function:

from flask import current_app

def fuu():
    current_app.logger.info('hello world')
    any = current_app.config['any']

Without any special context handling I receive following error message:

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.

After reading about Flask context, I came up with a working solution:

@classmethod
def setUpClass(cls):
    app = app_factory.create_app()
    ctx = app.app_context()
    ctx.push()
    cls.app = app

But the point is that I do not want to deal with any flask contexts in UNIT tests. I want to have a plain unit test, in which all collaborators can be mocked, so that the system under test just deals with mocked instance, in this case for current_app as well. Having flask context is pretty fine for integration testing, but not for unit testing.

I am searching for something similar like this:

 @patch('flask.current_app')

Is there any way to achieve this?

EDIT #1

@Gabriel C

service.py

from flask import current_app

def fuu():
    current_app.logger.info('hello world')

service_test.py

import unittest
from unittest.mock import patch

class TestService(unittest.TestCase):

@patch('flask.current_app')
def test_generate_image_happy_path(self, mock):
    from service import fuu
    fuu()
    assert 1 == 1

This fails for the same exact reason:

E           RuntimeError: Working outside of application context.

Upvotes: 8

Views: 7684

Answers (2)

Darius Mandres
Darius Mandres

Reputation: 928

Answering for anyone that runs into the same issue. What you can do is create a dummy Flask app and use its context in your test. No need to patch anything.

import unittest
from service import fuu


class TestService(unittest.TestCase):
    app = Flask('test')

    def test_generate_image_happy_path(self):
        with app.app_context():
            fuu()
            assert 1 == 1

Of course if you want to have access to your Flask config, you'd have to pass that in to this dummy app.

Upvotes: 7

Gabriel Cappelli
Gabriel Cappelli

Reputation: 4170

Edit: Correct patch when using from flask import current_app

service.py

from flask import current_app

def fuu():
    current_app.logger.info('hello world')

service_test.py

import unittest
from unittest.mock import patch


class TestService(unittest.TestCase):

    @patch('service.current_app')
    def test_generate_image_happy_path(self, mock):
        from service import fuu
        fuu()
        assert 1 == 1

Upvotes: 4

Related Questions