[英]Python 2.7 mock a void method of a class
我正在嘗試使用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()
的調用,如下面的文檔中所述。
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
嗎?
您提供的代碼不足以查看導致問題的部分。 我們需要查看模塊serviceregistry
才能確定,但我會做出有根據的猜測:
你有一個像這樣的文件a.py
(又名baseupgradehandler
):
class A:
def method(self):
print("It's real!")
和文件b.py
(又名serviceregistry
)是這樣的:
from a import A
class B:
def get_A(self):
return A()
在您的測試文件中,您執行以下操作:
import unittest
from unittest.mock import patch
from b import B
from a import A
游戲結束!
B
模塊現在已經獲得了對原始A
類的引用。 之后,當您patch('a.A')
僅更改了a
模塊中的引用,但patch
無法知道B
對原始A
有自己的引用。
您可以通過三種方式解決此問題:
補丁bA
太:
with patch('a.A') as h_a, patch('b.A') as h_b: h_a.return_value.method.return_value = '' h_b.return_value.method.return_value = ''
避免在修補之前導入模塊(可能不可行或一個好主意):
import unittest from unittest.mock import patch class MyTest(unittest.TestCase): def test_one(self): with patch('a.A') as h: h.return_value.method.return_value = '' from b import B B().get_A().method()
我已經使用 unittest.mocks 一段時間了,有時我一直在重新發明輪子。 我決定讓 mockito 成為我項目的一部分,現在事情看起來好多了。 任何類型的模擬驗證都非常簡單,如果可以的話,我絕對鼓勵您將 mockito 用作庫的一部分。 這個庫有一個很好的文檔,到目前為止它比 unittest.mock 恕我直言更容易。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.