【问题标题】:How to patch a method decorated with `flask - route` in testing?如何在测试中修补用`flask - route`装饰的方法?
【发布时间】:2020-06-26 11:34:56
【问题描述】:

我有一个 python 应用程序,它使用 Flask 来公开一些端点。另外,我使用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 时未应用 mock。但我不知道如何解决它。

【问题讨论】:

    标签: python flask mocking pytest


    【解决方案1】:

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

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

    注意到,给了我线索,问题依赖于烧瓶初始化和 pytest 夹具创建。

    但是,这样做会干扰烧瓶上下文的创建,并且应用在每个模拟方法上的装饰器没有正确应用。

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

    def mocked_function(**args):
        raise Exception(MOCKED_EXCEPTION_MESSAGE)
    
    def test_exception(client):
         client.application.view_functions["main.my_url_method"] = mocked_function
    

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

    【讨论】:

      猜你喜欢
      • 2018-02-14
      • 2012-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多