假设我有以下代码:
class MyClass:
def __init__(self, value=1):
self.value = value
self.destructive_stuff()
def destructive_stuff(self):
print("Running destructive commands on the host...")
def compute_value(self):
return self.value * 10
def main():
sample = MyClass(value=5)
print(f"Computed value: {sample.compute_value()}")
if __name__ == "__main__":
main()
我想测试
main()
功能。具体来说,我想检查 compute_value()
方法是否已被调用。我正在使用模拟,因为我不想初始化 MyClass
的真实实例,因为它会运行 destructive_stuff()
:
import unittest
from unittest.mock import patch
import my_sample
class TestPieq(unittest.TestCase):
@patch("my_sample.MyClass")
def test_called(self, mock_myclass):
my_sample.main()
mock_myclass.compute_value.assert_called()
但是,当我运行它时,它失败了:
$ python3 -m unittest tests.py
Computed value: <MagicMock name='MyClass().compute_value()' id='140298914799936'>
F
======================================================================
FAIL: test_called (tests.TestSample)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.10/unittest/mock.py", line 1379, in patched
return func(*newargs, **newkeywargs)
File "/tmp/pieq/tests.py", line 9, in test_called
mock_myclass.compute_value.assert_called()
File "/usr/lib/python3.10/unittest/mock.py", line 898, in assert_called
raise AssertionError(msg)
AssertionError: Expected 'compute_value' to have been called.
----------------------------------------------------------------------
Ran 1 test in 0.002s
FAILED (failures=1)
如果我直接在
patch
指令中定位该方法,我的测试会通过...但它使用真实的类,因此它调用 destructive_stuff()
方法!
class TestSample(unittest.TestCase):
@patch("my_sample.MyClass.compute_value")
def test_called(self, mock_myclass_compute):
my_sample.main()
mock_myclass_compute.assert_called()
$ python3 -m unittest tests.py
Running destructive commands on the host...
Computed value: <MagicMock name='compute_value()' id='140289139827584'>
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
如何实现我想要的?
由于它是您要测试的实例的方法,并且该实例是通过调用该类创建的,因此您应该在模拟类后面加上括号以获取用于测试的模拟实例:
mock_myclass().compute_value.assert_called()