我无法理解模拟补丁是如何工作的,以及它是否能够解决我的问题。
我有3个文件:与外部接口(a.py)通信,业务逻辑(b.py)和测试(test.py)。我想在运行测试时修补业务逻辑使用的外部接口。
a.py:
class SomeProductionClassINeedPatch(object):
name = 'Production Class (communication with some external service)'
def do_something(self):
print '<some feature with external service>'
b.py:
import mock
from src.tmp.mocks.a import SomeProductionClassINeedPatch
class WorkingClass(object):
def some_method_that_uses_external_class(self, *args):
external = self._external
external.do_something()
@property
def _external(self):
if not hasattr(self, '_ext_obj' or not self._ext_obj):
self._ext_obj = SomeProductionClassINeedPatch()
print isinstance(self._ext_obj, mock.MagicMock) # False
return self._ext_obj
b = WorkingClass()
b.some_method_that_uses_external_class()
test.py:
import mock
from src.tmp.mocks.b import WorkingClass # class I want to test
@mock.patch('src.tmp.mocks.a.SomeProductionClassINeedPatch')
def test_some_method_of_working_class(external_mock=None, *args):
o = WorkingClass()
o.some_method_that_uses_external_class() # external interface wasn't patched: <some feature with external service> - but I need mock here!
print '<test> - '+str(isinstance(o._external, mock.MagicMock)) # False
test_some_method_of_working_class()
我希望在 test.py 中调用o.some_method_that_uses_external_class()实际上不会使用外部接口,而是模拟对象。但似乎仍然使用了实际的对象。
当我在test.py或b.py中检查外部接口对象的实例时 - 我无法让它们通过 isinstance(object,MagicMock)检查,它总是返回false。即使我尝试在 b.py (作为类装饰器)中应用相同的补丁。我做错了什么?
如果重要的话,我使用python 2.7和Michael Foord的模拟库1.0。
答案 0 :(得分:0)
如Where to patch中所述:
补丁通过(暂时)更改名称指向的对象与另一个对象。可以有许多名称指向任何单个对象,因此要修补工作,您必须确保修补被测系统使用的名称。
在您的示例中,使用您要修补的对象的代码位于模块b
中。当您调用patch时,该类已经在模块b
中导入,因此修补a
对b
没有影响。您需要在b
:
@mock.patch('src.tmp.mocks.b.SomeProductionClassINeedPatch')
这将为您提供预期的结果,来自b
的第一个调用未修补,而来自test
的第二个调用使用了模拟对象:
# python test.py
False
<some feature with external service>
True
<test> - True