我的代码具有以下结构:
我有一个类MyClass
,它是从BaseClass
继承的(这只是偶然点,而不是问题的根源)。然后,我有另一个类MyClassManager
,它调用MyClass
的方法。
我正在为MyClassManager
的一种方法编写单元测试,我想控制MyClass
的其中一种方法的返回值,同时自动指定其余方法。
在测试中,我通过用MyClass
修补类为autospec=True
创建了一个模拟。然后,我尝试修补方法MyClass.method_to_patch
并将其替换为Substitute.substitute_method
。到目前为止,一切都很好。
但是现在我运行测试时,类管理器创建了MyClass
实例,它是一个完全自动指定的Mock,但没有修补我要替代的方法。
有没有办法将这两个patch
装饰器组合起来实现我想要的?
class Substitute:
def substitute_method(self, arg1, arg2):
print("Running substitute method")
return (arg1 > 0 and arg2 > 0)
class BaseClass:
def method_to_patch(self, arg1, arg2):
return arg1 == arg2
class MyClass(BaseClass):
def myclass_method(self):
print("myclass method called")
class MyClassManager:
def method_to_test(self):
my_class = MyClass()
my_class.myclass_method()
my_class.method_to_patch(10, 100)
class TestMyClass(unittest.TestCase):
@patch.object(MyClass, "method_to_patch", Substitute.substitute_method)
@patch("__main__.MyClass", autospec=True)
def test_method_to_test(self, mock_class):
class_manager = MyClassManager()
class_manager.method_to_test()
print(mock_class.call_count)
if __name__ == "__main__":
unittest.main()
答案 0 :(得分:0)
我在下一页找到了答案的线索,其中讨论了模拟嵌套属性调用:https://www.integralist.co.uk/posts/mocking-in-python/。相同的逻辑适用于方法调用。
仅仅手动调整模拟对象是不够的-您必须调整模拟对象的return_value
。
这是测试的外观:
class TestMyClass(unittest.TestCase):
@patch("__main__.MyClass", autospec=True)
def test_method_to_test(self, mock_class):
mock_class.return_value.method_to_patch = Substitute.substitute_method
class_manager = MyClassManager()
class_manager.method_to_test()
print(mock_class.call_count)
现在我有一个模拟对象代替了MyClass
,所以MyClass.myclass_method
也被模拟了,但是我可以根据需要用Substitute.substitute_method
代替MyClass.method_to_patch
。
最后一点说明-substitute_method
实际上是staticmethod
,因此应如下所示:
class Substitute:
@staticmethod
def substitute_method(arg1, arg2):
print("Running substitute method")
return (arg1 > 0 and arg2 > 0)
答案 1 :(得分:-1)
要模拟类中的方法以返回特定值,请使用@patch。目的。用@patch模拟类中的方法。对象,但每次调用时都返回不同的值,请使用side_effect。