【问题标题】:Mocking subprocess.check_call more than once多次模拟 subprocess.check_call
【发布时间】:2018-10-18 19:46:32
【问题描述】:

我有一个调用subprocess.check_call() 两次的函数。我想测试他们所有可能的输出。我希望能够将第一个 check_call() 设置为返回 1,将第二个设置为返回 0,并对所有可能的组合都这样做。以下是我到目前为止所拥有的。我不确定如何调整预期返回值

@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:

【问题讨论】:

  • 用切换(全局变量)存储以前的状态怎么样
  • 一般说明:您不需要强制迭代,只需执行for p, d in itertools.product([1, 0], repeat=2):

标签: python unit-testing mocking python-unittest


【解决方案1】:

您可以将模拟的side_effect 分配给一个可迭代对象,并且每次调用它都会返回该可迭代对象中的下一个值。在这种情况下,您可以这样做:

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 返回值上使用副本,因为如果我不这样做,它会使用原始迭代器。当我们想要的是 2 个单独的列表时,这会耗尽原始迭代器:一个用于模拟的 side_effect,另一个用于在测试中循环。
  • 您可以使用side_effect 做其他简洁的事情,而不仅仅是加注。如上图,可以更改多次调用的返回值:https://docs.python.org/3/library/unittest.mock-examples.html#side-effect-functions-and-iterables
    • 不仅如此,你还可以从上面的链接中看到,你还可以给它一个函数指针。这允许您在跟踪多个模拟调用时执行更复杂的逻辑。

【讨论】:

    猜你喜欢
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多