如何在测试中修补以“ flask-route”修饰的方法?

时间:2020-06-26 11:34:56

标签: python flask mocking pytest

我有一个使用Flask公开某些端点的python应用程序。另外,我正在使用fixture来捕获未处理的异常并返回自定义响应。这是一个示例代码:

from flask import make_response, Blueprint

root = Blueprint("main", __name__)

@root.errorhandler(Exception)
def custom_error_handler(error):
    #do other things here
    return make_response({"status": "failure", "error": str(error)}), 500

@root.route("/my_url", methods=["POST"])
def my_url_method():
    #do other thins
    return make_response(...), 200

我想进行测试以确保能正常工作。因此,为了模拟发生未处理的异常,我尝试使用简单引发异常的函数来模拟my_url method

from unittest.mock import patch
from flask import Flask

@pytest.fixture
def client(monkeypatch):
    app = Flask(__name__, instance_relative_config=True)
    app.register_blueprint(root)
    app.config["TESTING"] = True

    return app.test_client()

def test_exception(client):
    with patch("[file_link].my_url_method", side_effect=Exception("an error")):
        response = client.post("my_url")
        assert response.status_code == 500

但是断言失败。该方法可以正确执行,不会引发任何异常,并返回200作为状态代码。

我认为问题在于调用方法throw flask时没有应用模拟。但是我不知道如何解决。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。它不是最优雅的,但可以。 使用装饰器修补测试有效,因为在创建烧瓶上下文之前应用了修补:

@patch("[file_link].my_url_method", side_effect=Exception("an error")
def test_exception(client):
    #some code here

弄清楚这一点,这给了我一个线索,那就是问题取决于烧瓶的初始化和pytest夹具的创建。

但是,这样做会干扰flask上下文的创建,并且无法正确应用应用于每个模拟方法的装饰器。

因此,我没有进行“传统模拟”,而是简单地更新了烧瓶引用以获取必须在请求中调用的功能:

def mocked_function(**args):
    raise Exception(MOCKED_EXCEPTION_MESSAGE)

def test_exception(client):
     client.application.view_functions["main.my_url_method"] = mocked_function

为每个测试创建的client固定装置,因此它不会干扰套件中的其余测试。