模拟 class 实例的函数调用,该实例是 Python 中另一个 class 实例的成员
Mocking a function call of a class instance which is a member of another class instance in Python
我正在为这个版本使用 Python2.7 和模块 unittest
和 mock
。我有一种情况,我想模拟 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.
而失败,所以我猜它根本没有按照我的意图进行。我将如何去嘲笑这种行为并在之后对其进行断言?
- 因为你模拟了
Bin
,bin.inspect_rubbish()
是一个模拟调用,它什么都不做。
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
,因为这会出错。
我正在为这个版本使用 Python2.7 和模块 unittest
和 mock
。我有一种情况,我想模拟 class 实例的函数调用及其 return 值。麻烦的是,这个实例是另一个class实例的成员。让我在代码中澄清一下。
假设我在 my_package/bin.py
:
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.
而失败,所以我猜它根本没有按照我的意图进行。我将如何去嘲笑这种行为并在之后对其进行断言?
- 因为你模拟了
Bin
,bin.inspect_rubbish()
是一个模拟调用,它什么都不做。 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
,因为这会出错。