【问题标题】:How to Mock Attributes & Properties of Return Values with patch()如何使用 patch() 模拟返回值的属性和属性
【发布时间】:2019-08-01 22:45:37
【问题描述】:

test_client/wclient.py

import json
import requests
client = requests.session()

def setup():
    response = REST_CLIENT.post(
        "https://placeholder.com",
        auth=(placeholder, placeholder),
        data={"grant_type": "client_credentials"},
    )

    status_code = response.status_code
    if status_code in OK_STATUS:
        payload = json.loads(response.content, object_pairs_hook=OrderedDict)
    else:
        payload = response.text
        msg = (
            "Status Code %s" % status_code
        )
        logger.error(msg)
        raise ValueError(msg)

    return payload["access_token"]

测试文件: test_client/test_client.py

import mock
import wclient
@mock.patch("test_client.wclient")
def test_taxes_pitney_bowes_setup_success(resp):
    resp.return_value.post.return_value.status_code = "200"
    wclient.pitney_bowes_setup()

Status Code <MagicMock name='REST_CLIENT.post().status_code' id='4868492200'>

如何使用 mock.patch() 模拟模块的方法和属性?我已经阅读了堆栈溢出帖子的页面,但我对所有不同的方式来执行魔术模拟感到困惑。

我试过嘲笑:

resp.return_value.post.return_value.status_code
resp.return_value.post.return_value.status_code.return_value
resp.post.return_value.status_code
resp.post.return_value.status_code.return_value
resp.post.status_code
resp.post.status_code.return_value

【问题讨论】:

    标签: python unit-testing mocking attributes pytest


    【解决方案1】:

    我认为实际进行模拟的方法有很多种(请参阅Mocking Method Calls In Python 中的多种方法)。我喜欢这样做并且很容易进行简单模拟的方式是:

    对于函数: @patch('module.print', lambda x: None)

    对于属性: @patch('module.cwd', os.path.join(os.getcwd(), "folder"))

    这篇博文可能对您有所帮助:https://medium.com/uckey/how-mock-patch-decorator-works-in-python-37acd8b78ae

    如果您还有其他问题,请告诉我。

    编辑: 要添加多个模拟,只需添加另一个属性:

    import wclient
    @mock.patch("test_client.wclient")
    @mock.patch("another_attribute", "value")
    @mock.patch("another_function", lambda x, y: x + y)
    def test_taxes_pitney_bowes_setup_success(resp):
        resp.return_value.post.return_value.status_code = "200"
        wclient.pitney_bowes_setup()
    
    

    【讨论】:

    • 博客文章有助于我的一般理解,但我想我并没有真正看到它如何帮助解决当前的问题。 @patch('module.print', lambda x: None) 会将值设置为函数,不是吗?编辑:不小心点击了保存编辑。继续,如果我想保留一个通用的mock 对象,但能够为多个属性返回值,而不仅仅是status_code?如果我想为status_codetext 做这件事怎么办?如果我希望能够模拟两个帖子并在同一个方法中获取呢?
    • 正确,它会将模块中的打印功能更改为返回None。您可以使用它返回任何值并模拟出一个函数,或者使用它将变量更改为特定值(请参阅属性模拟)。编辑:您可以在测试上方添加多个补丁以指定不同的属性和功能。您还可以更改该 lambda 以接受多个参数并根据该输入返回多个参数。我可以将此示例添加到上面的答案中。
    • 你是说要模拟 post 对象的 status_code 和 text ,我需要模拟 post 方法吗?还是您建议我需要模拟 status_codetext 属性?
    • 跟进新的、已编辑的帖子。在这种情况下,MagicMock 对象是resp。使用多个 mock.patch 装饰器,resp 有效地模拟了什么?是test_client.wclient吗?一个对象怎么能解释多个匹配?编辑:我知道another_attributeanother_function 在装饰器中有它们的返回值。我的错!但这并不能解决未正确模拟的状态代码。
    • 我认为您的解决方案无法回答我的问题。这些都不适合当前的情况。
    猜你喜欢
    • 2018-10-08
    • 2018-12-04
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多