在Flask单元pytest中模拟current_app

Mocking current_app in Flask unit pytest

我想对以下功能进行单元测试:

1
2
3
4
5
from flask import current_app

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

没有任何特殊的上下文处理,我收到以下错误消息:

1
2
3
4
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.

在阅读了Flask上下文之后,我想出了一个可行的解决方案:

1
2
3
4
5
6
@classmethod
def setUpClass(cls):
    app = app_factory.create_app()
    ctx = app.app_context()
    ctx.push()
    cls.app = app

但是关键是我不想在UNIT测试中处理任何flask上下文。我想进行一个简单的单元测试,在其中可以模拟所有协作者,以便被测系统仅处理模拟实例,在本例中也适用于current_app
对于集成测试,具有烧瓶上下文非常好,但对于单元测试,则不是。

我正在搜索类似的内容:

1
 @patch('flask.current_app')

有什么办法可以做到这一点?

编辑#1

@Gabriel C

service.py

1
2
3
4
from flask import current_app

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

service_test.py

1
2
3
4
5
6
7
8
9
10
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

由于相同的确切原因,此操作失败:

1
E           RuntimeError: Working outside of application context.


编辑:使用from flask import current_app

时更正补丁

service.py

1
2
3
4
from flask import current_app

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

service_test.py

1
2
3
4
5
6
7
8
9
10
11
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


为遇到相同问题的任何人解答。您可以做的是创建一个虚拟Flask应用程序,并在测试中使用其上下文。无需打补丁。

1
2
3
4
5
6
7
8
9
10
11
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

当然,如果您想访问您的Flask配置,则必须将其传递给此虚拟应用。