【问题标题】:Path issues when attempting to patch or monkeypatch a function called in a Flask API尝试修补或猴子修补 Flask API 中调用的函数时的路径问题
【发布时间】:2018-12-12 20:30:32
【问题描述】:

我正在尝试为 Flask 应用程序构建一些测试,但我正在努力让一些模拟/修补程序按预期工作。

尽管花时间阅读/思考有关 where to patch 的文档,但 @patchmonkeypatch 的行为似乎都不像我预期的那样,我很难看出我做错了什么。

在 Flask api.py 文件中,我有一个简单的登录 API,用于检查身份验证要求(在其他地方定义并如图所示导入):

from project_name.api.auth import login_auth

@api.route('/v1/login', methods=['POST'])

    data = request.get_json()

    username = data['Username']
    password = data['Password']

    if not login_auth(username, password):
        raise APIError('Invalid Username or Password')
    ...

我有兴趣修补 login_auth 函数,这样我就可以在没有真实用户名/密码的情况下进行测试。

在我的 pytest 文件中,我尝试使用补丁和猴子补丁来解决这个问题。

@patch 方法:

@patch('project_name.api.auth.login_auth')
def test_login(mock_login_auth, client):
    mock_login_auth.return_value = True
    mimetype = 'application/json'
    headers = {
        'Content-Type': mimetype,
        'Accept': mimetype
    }
    data = {
        'Username': "test_user",
        'Password': "test_password",
    }
    url = 'api/v1/login'

    assert project_name.api.auth.login_auth('x', 'y') == True                                                                                                                                                                                                               

    response = client.post(url, data=json.dumps(data), headers=headers)
    assert response.status_code == 200

如果我运行这个测试,那么直接调用修补函数的第一个断言语句将按预期工作,但是 API 调用将不会使用模拟的 login_auth 函数,并且测试将不符合此标准。

monkeypatch 方法:

def test_login2(client, monkeypatch):
    monkeypatch.setattr("project_name.api.auth.login_auth", lambda x, y: True)
    mimetype = 'application/json'
    headers = {
        'Content-Type': mimetype,
        'Accept': mimetype
    }
    data = {
        'Username': "test_user",
        'Password': "test_password",
    }
    url = 'api/v1/login'

    assert project_name.api.auth.login_auth('x', 'y') == True                                                                                                                                                                                                               

    response = client.post(url, data=json.dumps(data), headers=headers)
    assert response.status_code == 200

我再次看到第一个断言,它直接调用该函数,并按预期进行了修补,但在对 API 的请求之后调用的函数尚未修补,因此测试将在第二个 assert 上失败声明。

我尝试了许多不同的方法,包括尝试修补路径 project_name.api.login_auth 处的 login_auth(假设我正在尝试修补导入到 api.py 中的特定 login_auth 函数文件),但我不清楚正确的方法。

鉴于我正在使用 Flask 的 test_client 方法,我想知道是否需要做一些具体的事情,或者我是否还缺少其他东西。

【问题讨论】:

  • 您在第一个示例中的装饰器无效。
  • 看看this question。你的问题很相似。
  • 这正是我一直在抨击的同一个问题。我非常有兴趣找到一种可行的技术。

标签: python unit-testing flask mocking pytest


【解决方案1】:

这里的问题是你在api.py 中导入了模块的一个函数

from project_name.api.auth import login_auth

似乎命名空间需要匹配,因此作为解决方法,您可以导入整个模块并使用完整的命名空间调用函数:

if not project_name.api.auth.login_auth(username, password):

您也可以查看其他问题: mocking functions using python mock

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 2012-03-13
    • 2013-12-26
    • 2012-06-14
    • 2012-03-29
    • 1970-01-01
    相关资源
    最近更新 更多