簡體   English   中英

Python Mock Patch 類中的多個方法

[英]Python Mock Patch multiple methods in a class

我試圖修補一個類中的多個方法。 這是我的簡化設置

Hook.py 定義為

class Hook():
    def get_key(self):
        return "Key"

    def get_value(self):
        return "Value"

HookTransfer.py 定義為

from Hook import Hook

class HookTransfer():
    def execute(self):
        self.hook = Hook()
        key = self.hook.get_key()
        value = self.hook.get_value()
        print(key)
        print(value)

我想模擬 Hook 類中的 get_key 和 get_value 方法。 以下作品即打印 New_Key 和 New_Value

from HookTransfer import HookTransfer
import unittest
from unittest import mock

class TestMock(unittest.TestCase):
    @mock.patch('HookTransfer.Hook.get_key', return_value="New_Key")
    @mock.patch('HookTransfer.Hook.get_value', return_value="New_Value")
    def test_execute1(self, mock_get_key, mock_get_value):
        HookTransfer().execute()

if __name__ == '__main__':
    unittest.main()

然而這並沒有。 它打印<MagicMock name='Hook().get_key()' id='4317706896'><MagicMock name='Hook().get_value()' id='4317826128'>

from HookTransfer import HookTransfer
import unittest
from unittest import mock

class TestMock(unittest.TestCase):
    @mock.patch('HookTransfer.Hook', spec=True)
    def test_execute2(self, mock_hook):
        mock_hook.get_key = mock.Mock(return_value="New_Key")
        mock_hook.get_value = mock.Mock(return_value="New_Value")
        HookTransfer().execute()

if __name__ == '__main__':
    unittest.main()

直覺上,似乎第二個也應該工作,但事實並非如此。 你能幫助解釋為什么它沒有。 我懷疑它與“在哪里修補”有關,但我無法弄清楚。

您可以使用patch.multiple()修補模塊或類的多個方法。 這樣的事情應該適用於您的情況:

import unittest
from unittest.mock import MagicMock, patch

class TestMock(unittest.TestCase):
    @patch.multiple('HookTransfer.Hook',
                    get_key=MagicMock(return_value='New_Key'),
                    get_value=MagicMock(return_value='New_Value'))
    def test_execute1(self, **mocks):
        HookTransfer().execute()

patch.multiple()作為裝飾器使用時,mocks通過關鍵字傳遞給被裝飾的函數,當它作為上下文管理器使用時返回一個字典。

你需要的是:

模擬 Hook 類,

from HookTransfer import HookTransfer
from Hook import Hook

import unittest
try:
    import mock
except ImportError:
    from unittest import mock

class TestMock(unittest.TestCase):
    @mock.patch.object(Hook, 'get_key', return_value="New_Key")
    @mock.patch.object(Hook, 'get_value', return_value="New_Value")
    def test_execute1(self, mock_get_key, mock_get_value):
        HookTransfer().execute()

if __name__ == "__main__":
    unittest.main()

經過一些測試,我能夠找到問題所在。

在第二個測試用例中,補丁裝飾器創建一個 Mock 類的新實例,並通過 mock_hook 參數將其傳遞給 test_execute2 函數。 讓我們將其稱為 mock1。 mock1 替換了 HookTransfer.py 中的 Hook 類。 self.hook = Hook()運行時,它轉換為調用 mock1 的__init__ 按照設計,這會返回另一個 Mock 實例 - 讓我們將其稱為 mock2。 所以self.hook指向mock2。 但是mock_hook.get_key = mock.Mock(return_value="New_Key") ,mock1 中的方法。

為了正確模擬,mock2 需要打補丁。 這可以通過兩種方式完成

  1. 通過模擬mock1的return_value(返回mock2) mock_hook.return_value.get_key = mock.Mock(return_value="New_Key")
  2. 模擬mock1(返回mock2)的構造函數的返回值mock_hook().get_key = mock.Mock(return_value="New_Key")

在幕后,這兩個選項確實做同樣的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM