【发布时间】:2018-11-18 11:25:28
【问题描述】:
我正在尝试使用unittests.mock 来模拟对象的 void 方法调用。
我的包裹如下
common
baseupgradehandler.py
baseupgradehandler.py
class BaseUpgradeHandler(object):
def __init__(self, upgrade_config, upgrade_state, system_config, pre_step, main_step, post_step):
...
# Method call to be supressed
def start(self, service_manifest, upgrade_bundle):
# type: (service_version_pb2.ServiceManifest, str) -> ()
...
在我的测试代码中,我试图模拟对start() 的调用,如下所示,如documentation 中所述。
from workflow.upgradeworkflow import UpgradeWorkflow
from common.serviceregistry import ServiceRegistry
# The above imports are at the start of the test file
...
with patch('common.baseupgradehandler.BaseUpgradeHandler') as handler_mock: # type: Mock
handler_mock.return_value.start.return_value = ''
wf = UpgradeWorkflow(ServiceRegistry(self.service_bundle, config, sys_config, state),
config,
state,
sys_config)
BaseUpgradeHandler 对象由ServiceRegistry 的get_upgrade_handler() 方法返回。当我在测试中执行上述代码时,我看到BaseUpgradeHandler.start() 仍在被调用。
有人可以告诉我如何模拟对start() 的调用,以便不调用该方法吗?
编辑
如果我像下面这样更改我的补丁代码,它会按预期工作,BaseUpgradeHandler 会被嘲笑,start 不会被调用。
with patch('common.baseupgradehandler.BaseUpgradeHandler') as handler_mock: # type: Mock
handler_mock.return_value.start.return_value = ''
with patch('common.serviceregistry.ServiceRegistry') as serviceregistry_mock: # type: Mock
serviceregistry_mock.return_value.get_upgrade_handler.return_value = handler_mock
wf = UpgradeWorkflow(ServiceRegistry(self.service_bundle, config, sys_config, state), config, state, sys_config)
wf.start()
谁能解释我为什么还要修补ServiceRegistry?
【问题讨论】:
-
patch用作上下文管理器仅修补with块内的方法。你可能在外面叫它。如果您想为整个测试方法修补该方法,请使用patch作为装饰器。另外:如果你想patch('mcommon.baseupgradehandler.BaseUpgradeHandler.start') as method: method.return_value = '',你可以只模拟方法 -
@Bakuriu - 不,我没有在外面打电话。我已经编辑了这个问题。我不想修补整个测试方法。所以我使用了
with。如果我遵循您的建议并制作patch('mcommon.baseupgradehandler.BaseUpgradeHandler.start') as method: method.return_value = '',那么这将按预期工作。我有多种方法可以模拟BaseUpgradeHandler。那么我必须按照您的建议模拟每种方法还是有其他方法? -
我无法重现您的问题。您如何检查是否调用了真正的方法?我们需要一个重现问题的完整示例,以了解为什么补丁在您的情况下不起作用。也许您正在通过修补之前获取的引用访问该类。如果你把
patch作为装饰器,这个行为还会发生吗? -
@Bakuriu - 我已经编辑了我的问题。它是更大代码库的一部分。我将尝试有一个完整的玩具示例。但是,如果上述编辑提供任何线索,请告诉我。
-
只是提示:您来自庞大的代码库并不重要。首先“注释掉”该测试未使用的所有代码。然后注释掉该单个测试未直接使用的所有类/函数/方法。然后更改查找文件/数据库的函数的实现以仅返回固定结果。现在不管你来自哪里,你应该有非常少的类,几乎没有实现。看看问题是否仍然存在。如果没有尝试添加更多代码并重复。大多数情况下,通过这个过程,您会找到答案。
标签: python python-2.7 unit-testing