如何模拟对象方法返回值

问题描述 投票:0回答:3

我目前拥有的是:

def some_method():
    some_obj = some_other_method()
    # This is what I want to mock return value of:
    some_obj.some_obj_some_method()

@patch('some_package.some_other_method')
def test_some_stuff(some_other_method_patch):
    some_other_method_patch.return_value = SomeObject()

如何将 some_obj.some_obj_some_method() 返回值设置为 False?

python unit-testing mocking pytest python-mock
3个回答
9
投票

patch('some_package.some_other_method')
将用
some_other_method
替换函数
Mock
。现在您需要替换此模拟的方法
some_obj_some_method
的返回值:

mock.return_value.some_obj_some_method.return_value = False

完整示例:

# some_package.py

class SomeObject:
    def some_obj_some_method(self):
        raise RuntimeError()


def some_other_method():
    return SomeObject()


def some_method():
    some_obj = some_other_method()
    # This is what you want to mock return value of:
    return some_obj.some_obj_some_method()

测试:

from unittest.mock import patch
from some_package import SomeObject, some_method

@patch('some_package.some_other_method')
def test_some_stuff(function_mock):
    function_mock.return_value.some_obj_some_method.return_value = False
    assert not some_method()

测试将按原样通过,将在不修补的情况下引发

RuntimeError
,并且在没有
function_mock.return_value.some_obj_some_method.return_value = False
行的情况下使断言失败,因为
some_method
只会返回永远不是
Mock
False


2
投票

您可以使用

patch.object

import mock
import some_obj
@mock.patch.object(some_obj, "some_obj_some_method")
def test_some_stuff(mock_some_obj_some_method):
    mock_some_obj_some_method.return_value = False

0
投票

感谢@hoefling 的关键文章

return_value.object_method_name.return_value
,当我第一次看到它时,它非常令人困惑。这是一个简单的例子。

首先要测试的简单代码

sscce.py
。它使用第三方库中的类
pymisp
。为了进行测试,我需要模拟类构造函数(以便它不会通过网络连接)和一个对象方法。

from pymisp import PyMISP
misp_url = 'http://bogus.misp.org'
misp_key = 'redacted'


def orgs() -> list:
    # fetch and return the list of organisations
    client = PyMISP(url=misp_url, key=misp_key)
    return client.organisations(pythonify=True)

接下来使用模拟的测试文件来练习简单的代码:

from unittest.mock import patch
from my_sscce_module import sscce


# mock the class to intercept calls to the __init__ method
# note this uses the location where the class is looked up,
# not the location where the PyMISP class is defined
@patch('my_sscce_module.sscce.PyMISP')
def test_sscce(mock_pymisp):
    # define the expected result
    exp_orgs = ['org1', 'org2']
    # mock the object method to return a fixed value
    mock_pymisp.return_value.organisations.return_value = exp_orgs
    # call the function under test
    act_orgs = sscce.orgs()
    # assert that a class instance was created
    mock_pymisp.assert_called()
    # check for the expected result
    assert act_orgs == exp_orgs
© www.soinside.com 2019 - 2024. All rights reserved.