如何提取存储在 mock.call 中的参数
How to extract parameters stored in mock.call
我正在对以下功能进行单元测试:
import uuid
def process_name(id, name, weight):
print('process_item:', id, name, weight)
def process_list(names):
for (name, weight) in names:
id = uuid.uuid4()
process_name(id, name, weight)
我的单元测试如下所示:
import unittest
from mock import patch, call
import SomePackage.SomeModule
class MyTestCase(unittest.TestCase):
def test_something(self):
items = [('Joe', 190), ('Dan', 200)]
with patch('SomePackage.SomeModule.process_name') as mock_process_name:
SomePackage.SomeModule.process_list(items)
我无法匹配整个 mock_calls
东西,因为提交给它的第一个参数是一个 guid,因此每次调用函数时它都会不同:
print(mock_process_name.mock_calls)
[call(UUID('some randomish guid'), 'Joe', 190),
call(UUID('some other guid'), 'Dan', 200)]
我要提取参数,只匹配非易失性参数:
print(mock_process_name.mock_calls[0][1][1:])
print(mock_process_name.mock_calls[1][1][1:])
('Joe', 190)
('Dan', 200)
我知道我也可以模拟 returns guid 的东西,并在它的 side_effect 中提供一个固定的值列表。但是,我觉得很懒惰需要模拟太多东西,比如 uuid.uuid4()
、datetime.now()
等等。这就是为什么我正在寻找一种替代方法来模拟每个 volatile 函数。
是否有比 mock_calls[0][1][1:]
更具可读性的替代方案?
有人提议在某处支持此用例(错误或模拟回购?)但据我所知,它尚未实施。
现在您可以按照我的喜好顺序选择这些选项:
检查你需要什么
assert "Joe" in xx.mock_calls[0][1]
assert 190 in xx.mock_calls[0][1]
还有一个好处是,当测试失败时,您可以确切地知道这两个测试中的哪个失败了。
模拟 UUID
用可预测的顺序模拟它,然后你就可以验证你的调用了。
使用mock.ANY
xx.assert_called_with(mock.ANY, "Dan", 200)
遗憾的是,仅适用于最后一次调用。
你可以分解你的测试。
assert_any_call
xx.assert_any_call(mock.ANY, "Joe", 190)
但是您无法验证 Joe 和 Dan 的相对顺序。
mock.ANY 迂回
assert xx.mock_calls[0][1] == (mock.ANY, "Joe", 190)
进行断言的最简单方法是
mock_process_name.assert_has_calls([call(ANY, "Dan", 200), call(ANY, "Joe", 190)])
其中 ANY
是从 mock
模块
导入的助手
如果您对调用顺序不感兴趣,可以使用 any_order=True
选项。此外,如果您的连锁调用很复杂,您可以查看 Tracking order of calls and less verbose call assertions.
我正在对以下功能进行单元测试:
import uuid
def process_name(id, name, weight):
print('process_item:', id, name, weight)
def process_list(names):
for (name, weight) in names:
id = uuid.uuid4()
process_name(id, name, weight)
我的单元测试如下所示:
import unittest
from mock import patch, call
import SomePackage.SomeModule
class MyTestCase(unittest.TestCase):
def test_something(self):
items = [('Joe', 190), ('Dan', 200)]
with patch('SomePackage.SomeModule.process_name') as mock_process_name:
SomePackage.SomeModule.process_list(items)
我无法匹配整个 mock_calls
东西,因为提交给它的第一个参数是一个 guid,因此每次调用函数时它都会不同:
print(mock_process_name.mock_calls)
[call(UUID('some randomish guid'), 'Joe', 190),
call(UUID('some other guid'), 'Dan', 200)]
我要提取参数,只匹配非易失性参数:
print(mock_process_name.mock_calls[0][1][1:])
print(mock_process_name.mock_calls[1][1][1:])
('Joe', 190)
('Dan', 200)
我知道我也可以模拟 returns guid 的东西,并在它的 side_effect 中提供一个固定的值列表。但是,我觉得很懒惰需要模拟太多东西,比如 uuid.uuid4()
、datetime.now()
等等。这就是为什么我正在寻找一种替代方法来模拟每个 volatile 函数。
是否有比 mock_calls[0][1][1:]
更具可读性的替代方案?
有人提议在某处支持此用例(错误或模拟回购?)但据我所知,它尚未实施。
现在您可以按照我的喜好顺序选择这些选项:
检查你需要什么
assert "Joe" in xx.mock_calls[0][1]
assert 190 in xx.mock_calls[0][1]
还有一个好处是,当测试失败时,您可以确切地知道这两个测试中的哪个失败了。
模拟 UUID
用可预测的顺序模拟它,然后你就可以验证你的调用了。
使用mock.ANY
xx.assert_called_with(mock.ANY, "Dan", 200)
遗憾的是,仅适用于最后一次调用。 你可以分解你的测试。
assert_any_call
xx.assert_any_call(mock.ANY, "Joe", 190)
但是您无法验证 Joe 和 Dan 的相对顺序。
mock.ANY 迂回
assert xx.mock_calls[0][1] == (mock.ANY, "Joe", 190)
进行断言的最简单方法是
mock_process_name.assert_has_calls([call(ANY, "Dan", 200), call(ANY, "Joe", 190)])
其中 ANY
是从 mock
模块
如果您对调用顺序不感兴趣,可以使用 any_order=True
选项。此外,如果您的连锁调用很复杂,您可以查看 Tracking order of calls and less verbose call assertions.