提前道歉,如果我没有理解您尝试做什么,但我认为这可能有效:
import unittest
from unittest.mock import patch
class MyClass:
def __init__(self):
self.x = 0
self.y = 0
def some_method(self):
self.x = 4
self.y = 6
class OtherClass:
def other_method(self):
self.x = 5
self.y = 16
class MyTestClass(unittest.TestCase):
@patch('__main__.MyClass.some_method', new=OtherClass.other_method)
def test_patched(self):
a = MyClass()
a.some_method()
self.assertEqual(a.x, 5)
self.assertEqual(a.y, 16)
def test_not_patched(self):
a = MyClass()
a.some_method()
self.assertEqual(a.x, 4)
self.assertEqual(a.y, 6)
if __name__ == "__main__":
unittest.main()
当打补丁时,此操作将 some_method() 替换为 other_method(),并为属性 x、y 设置不同的值。运行测试时,会得到以下结果:
..
----------------------------------------------------------------------
Ran 2 tests in 0.020s
OK
编辑:回答如何在测试函数中不使用模拟类的问题...
def test_inside_patch(self):
def othermethod(self):
self.x = 5
self.y = 16
patcher = patch('__main__.MyClass.some_method', new=othermethod)
patcher.start()
a = MyClass()
a.some_method()
self.assertEqual(a.x, 5)
self.assertEqual(a.y, 16)
patcher.stop()
确保在patcher上调用start()和stop(),否则可能会出现补丁处于活动状态但您不希望它处于活动状态的情况。请注意,在测试代码函数内定义模拟函数时,我没有使用patch作为装饰器,因为必须在patch中使用“new”关键字之前定义模拟函数。如果您想使用patch作为装饰器,您必须在patch之前定义模拟函数,将其定义在MyTestClass中也可以工作,但似乎您真的希望在测试函数代码内定义模拟函数。
编辑:添加了我看到的四种方法的摘要...
class OtherClass:
def other_method(self):
...
class MyTest(unittest.TestCase):
@patch('path_to_MyClass.some_method', new=OtherClass.other_method)
def test_1(self)
...
class MyOtherClass:
def other_method(self):
...
@patch('path_to_MyClass.some_method', new=MyOtherClass.other_method)
def test_2(self):
...
def another_method(self):
...
@patch('path_to_MyClass.some_method', new=another_method)
def test_3(self):
...
def test_4(self):
def yet_another_method(self):
...
patcher = patch('path_to_MyClass.some_method', new=yet_another_method)
patcher.start()
...
patcher.stop()
这些都没有使用side_effect,但它们都解决了模拟类方法和更改一些属性的问题。你选择哪个取决于应用程序。