模拟 class 实例的函数调用,该实例是 Python 中另一个 class 实例的成员

Mocking a function call of a class instance which is a member of another class instance in Python

我正在为这个版本使用 Python2.7 和模块 unittestmock。我有一种情况,我想模拟 class 实例的函数调用及其 return 值。麻烦的是,这个实例是另一个class实例的成员。让我在代码中澄清一下。

假设我在 my_package/bin.py:

中定义了一个 class Bin
class Bin():
    def __init__(self):
        # code to initialize other stuff
        self.rubbish = self.fill_with_rubbish()  # creates list of rubbish instances

    def inspect_rubbish(self):
        inspection_results = []
        for rubbish in self.rubbish:
            inspection_results.append(rubbish.inspect())

我也在my_package/rubbish.py中定义了classRubbish:

class Rubbish():
    def __init__(self):
        # initialization stuff

    def inspect(self):
        return 'Nice rubbish'   

现在,在我的 /tests 文件夹中,我有一个测试文件 test_bin.py,我在其中设置环境并导入 bin 和垃圾,如下所示:

import my_package.bin as _bin
import my_package.rubbish as _rubbish

我正在尝试测试 Bin class 的 inspect_rubbish()。上面显然不是我的生产代码,但在我的原始代码中,我希望能够修改 Rubbish 实例的 inspect 的返回值并执行各种 assert调用它来检查它被调用了多少次等等。

我一直对如何实际模拟 Bin 实例的 Rubbish 实例的方法感到困惑。我试图通过一些补丁来解决这个问题,但无济于事。

def test_inspect_rubbish(self):
    with patch('my_package.bin.Bin', autospec=True) as mock_bin, \
        patch.object('my_package.rubbish.Rubbish.inspect') as mock_inspect:

        mock_inspect.return_value = 'Bad rubbish'

        bin = _bin.Bin()
        bin.rubbish = [MagicMock(), MagicMock()]
        result = bin.inspect_rubbish()

        mock_inspect.assert_called()

但是此代码因 AssertionError: Expected 'inspect' to have been called. 而失败,所以我猜它根本没有按照我的意图进行。我将如何去嘲笑这种行为并在之后对其进行断言?

  1. 因为你模拟了 Binbin.inspect_rubbish() 是一个模拟调用,它什么都不做。
  2. bin.rubbish = [MagicMock(), MagicMock()] 意味着永远不会调用模拟的 Rubbish.inspect,每个模拟只调用 MagicMock().inspect

此代码有效:

def test_inspect_rubbish(self):
    with patch('my_package.rubbish.Rubbish.inspect') as mock_inspect:

        mock_inspect.return_value = 'Bad rubbish'

        bin = _bin.Bin()
        bin.rubbish = [_rubbish.Rubbish(), _rubbish.Rubbish()]
        result = bin.inspect_rubbish()

        mock_inspect.assert_called()

演示:https://repl.it/repls/RundownTastyKernel

我也将 patch.object 更改为 patch,因为这会出错。