【发布时间】:2019-06-11 18:49:19
【问题描述】:
我正在尝试使用 @patch 装饰器和模拟对象来测试我的代码消耗一些库的行为。不幸的是,我看不到任何方法可以只使用装饰器来做我想做的事情,而且似乎我应该能够做到。我意识到通常我应该更关心方法的返回值,而不是它对库的特定调用序列,但是编写一个测试来比较一个图像和另一个图像是非常困难的。
我想也许我可以创建我的模拟对象的实例,然后使用@patch.object(...),但这不起作用,显然@patch('MockObject.method') 只会模拟类方法。我可以使用with patch.object(someMock.return_value, 'method') as mockName 使代码正常工作,但这会使我的测试变得混乱。
from some.module import SomeClass
class MockObject:
def method(self):
pass
class TestClass:
@patch('SomeClass.open', return_value=MockObject())
@patch('??????.method') # I can't find any value to put here that works
def test_as_desired(self, mockMethod, mockOpen):
instance = SomeClass.open()
instance.method()
mockOpen.assert_called_once()
mockMethod.assert_called_once()
@patch('SomeClass.open', return_value=MockObject())
def test_messy(self, mockOpen):
with patch.object(mockOpen.return_value, 'method') as mockMethod:
instance = SomeClass.open()
instance.method()
mockOpen.assert_called_once()
mockMethod.assert_called_once()
【问题讨论】:
-
补丁是用来修改创建超出你控制范围的对象;
MockObject的实例并非如此。 -
我要修补
MockObject.method的原因是为了验证该方法确实被调用(以及我期望的参数,为了简单起见,我在这个例子中省略了) -
所以在实例化的时候配置它;不要试图在事后修补它。
-
我将它实例化为另一个
@patch的返回值。再说一次,我想@patch模拟对象上的方法的原因是我可以将它注入测试函数并确保它被正确调用。 -
感谢 cmets 和建议。不过,我尝试做我想做的事情是有原因的。
标签: python unit-testing mocking pytest