不止一次嘲笑 subprocess.check_call
Mocking subprocess.check_call more than once
我有一个调用 subprocess.check_call()
两次的函数。我想测试所有可能的输出。我希望能够将第一个 check_call()
设置为 return 1,将第二个设置为 return 0,并对所有可能的组合都这样做。以下是我到目前为止所拥有的。我不确定如何调整预期的 return 值
@patch('subprocess.check_call')
def test_hdfs_dir_func(mock_check_call):
for p, d in list(itertools.product([1, 0], repeat=2)):
if p or d:
您可以将您的 mock 的 side_effect
分配给一个可迭代对象,这将在每次调用它时 return 迭代对象中的下一个值。在这种情况下,您可以这样做:
import copy
import itertools
import subprocess
from unittest.mock import patch
@patch('subprocess.check_call')
def test_hdfs_dir_func(mock_check_call):
return_values = itertools.product([0, 1], repeat=2)
# Flatten the list; only one return value per call
mock_check_call.side_effect = itertools.chain.from_iterable(copy.copy(return_values))
for p, d in return_values:
assert p == subprocess.check_call()
assert d == subprocess.check_call()
注意几点:
- 我没有你的原始函数,所以我在循环中调用了自己对
check_call
的调用。
- 我在原始
itertools.product
return 值上使用副本,因为如果我不这样做,它将使用原始迭代器。当我们想要的是 2 个单独的列表时,这会耗尽原始迭代器:一个用于模拟的 side_effect,另一个用于您在测试中循环。
- 您可以使用
side_effect
做其他巧妙的事情,而不仅仅是加注。如上所示,多次调用可以更改return值:https://docs.python.org/3/library/unittest.mock-examples.html#side-effect-functions-and-iterables
- 不仅如此,从上面的link可以看出,还可以给它一个函数指针。这允许您在跟踪多个模拟调用时执行更复杂的逻辑。
我有一个调用 subprocess.check_call()
两次的函数。我想测试所有可能的输出。我希望能够将第一个 check_call()
设置为 return 1,将第二个设置为 return 0,并对所有可能的组合都这样做。以下是我到目前为止所拥有的。我不确定如何调整预期的 return 值
@patch('subprocess.check_call')
def test_hdfs_dir_func(mock_check_call):
for p, d in list(itertools.product([1, 0], repeat=2)):
if p or d:
您可以将您的 mock 的 side_effect
分配给一个可迭代对象,这将在每次调用它时 return 迭代对象中的下一个值。在这种情况下,您可以这样做:
import copy
import itertools
import subprocess
from unittest.mock import patch
@patch('subprocess.check_call')
def test_hdfs_dir_func(mock_check_call):
return_values = itertools.product([0, 1], repeat=2)
# Flatten the list; only one return value per call
mock_check_call.side_effect = itertools.chain.from_iterable(copy.copy(return_values))
for p, d in return_values:
assert p == subprocess.check_call()
assert d == subprocess.check_call()
注意几点:
- 我没有你的原始函数,所以我在循环中调用了自己对
check_call
的调用。 - 我在原始
itertools.product
return 值上使用副本,因为如果我不这样做,它将使用原始迭代器。当我们想要的是 2 个单独的列表时,这会耗尽原始迭代器:一个用于模拟的 side_effect,另一个用于您在测试中循环。 - 您可以使用
side_effect
做其他巧妙的事情,而不仅仅是加注。如上所示,多次调用可以更改return值:https://docs.python.org/3/library/unittest.mock-examples.html#side-effect-functions-and-iterables- 不仅如此,从上面的link可以看出,还可以给它一个函数指针。这允许您在跟踪多个模拟调用时执行更复杂的逻辑。