Python:用于数组的Mock Patch模块
这是我的方法:
def _eda_workflow(self, workflow_id, account_id):
uuids = [str(uuid.uuid4()) for x in range(2)]
return {
'id': workflow_id,
'root': uuids[0],
'accountId': account_id,
'steps': [
{
'this': uuids[0],
'next': [uuids[1]],
'type': 'on-contact-signed-up',
'displayName': 'Sign Up',
'constraints': {},
},
{
'this': uuids[1],
'prev': uuids[0],
'next': [],
'type': 'on-time-elapsed',
'displayName': 'Send the email after delay or not!',
'delay': 'PT0M',
'sideEffect': {
'task': 'sendEmail',
'constraints': {},
'mailing_data': {},
'email': {}
}
}
]
}
我遇到的问题是,当我写这个的时候
def generate_uuids():
return ["10e6e848-dc77-4057-890e-5acd4ed9aeb3", "d8d501a7-f7e7-4423-921c-e0f39b7e1301"]
@mock.patch('path.to.uuid')
def test_translte_workflow(self, uuid_mock):
uuid_mock.uuid4.side_effect = generate_uuids
返回的方法给我返回的是一个列表
的值,而不是我期待的结果。我不太确定该怎么正确地写这个测试。
3 个回答
1
我遇到了一个类似的问题,经过一些尝试,我发现使用可迭代对象配合 @patch
和 side_effect
更好。在我的情况下,我不是填充一个数组,而是填充一个比我测试中的函数更深一层的函数的返回值。
TEST_UUIDS = ["10e6e848-dc77-4057-890e-5acd4ed9aeb3",
"d8d501a7-f7e7-4423-921c-e0f39b7e1301"]
TEST_UUID_POOL = iter(TEST_UUIDS)
@patch('path.to.function1', side_effect=TEST_UUID_POOL)
def test_translate_workflow(self, uuid_mock):
# function 1 is called twice in function2
function2()
2
你的 generate_uuids
函数返回的是一个 UUID 的 列表,所以你得到的就是这个。
如果你想要一个函数,每次只返回一个 UUID,并且这个 UUID 是从正好两个 UUID 中选出来的,你可以从这两个 UUID 的列表中创建一个 迭代器,然后在这个函数中返回 iterator.next()
。如果你还想对这些 UUID 进行一些检查,可以把它们单独存放,不要和迭代器放在一起:
import mock
import unittest
import uuid
TEST_UUIDS = ["10e6e848-dc77-4057-890e-5acd4ed9aeb3",
"d8d501a7-f7e7-4423-921c-e0f39b7e1301"]
uuid_pool = iter(TEST_UUIDS)
def generate_uuid():
return uuid_pool.next()
def func():
uuid_1 = uuid.uuid4()
uuid_2 = uuid.uuid4()
return [uuid_1, uuid_2]
class TestUUIDs(unittest.TestCase):
@mock.patch('uuid.uuid4', generate_uuid)
def test_uuid_mock(self):
actual = func()
expected = TEST_UUIDS
self.assertEquals(expected, actual)
unittest.main()
一旦你用完了这个迭代器(取出两个元素后),它会抛出 StopIteration
的错误。
如果你想创建一个函数,它总是从一个无尽的 UUID 流中返回一个 UUID,你可以使用 itertools.cycle
:
from itertools import cycle
uuid_pool = cycle(["10e6e848-dc77-4057-890e-5acd4ed9aeb3",
"d8d501a7-f7e7-4423-921c-e0f39b7e1301"])
3
副作用就是指在每次调用这个模拟对象时,额外发生的一些事情。我觉得这正是你想要的内容:
def fake_uuid4():
yield "10e6e848-dc77-4057-890e-5acd4ed9aeb3"
yield "d8d501a7-f7e7-4423-921c-e0f39b7e1301"
@mock.patch('path.to.uuid.uuid4', fake_uuid4().next)
def test_translte_workflow(self):
...