Python Mock Patch multiple methods in a class
After some testing I was able to find the issue.
In the second test case, the patch decorator creates a new instance of a Mock class and passes it via mock_hook argument to test_execute2 function. Lets refer to this as mock1. mock1 replaces the Hook class in HookTransfer.py. When self.hook = Hook()
is run, it translates to calling __init__
of mock1. By design this returns yet another Mock instance - lets refer to this as mock2. So self.hook points to mock2. But mock_hook.get_key = mock.Mock(return_value="New_Key")
, mocks the methods in mock1.
In order to mock correctly, mock2 needs to be patched. This can be done in 2 ways
- By mocking the return_value of mock1 (which returns mock2)
mock_hook.return_value.get_key = mock.Mock(return_value="New_Key")
- Mocking the return value of constructor of mock1 (which returns mock2)
mock_hook().get_key = mock.Mock(return_value="New_Key")
Under the wraps both options really do the same thing.
What you need to is:
mock the class 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_value, mock_get_key):
HookTransfer().execute()
if __name__ == "__main__":
unittest.main()
You can patch multiple methods of a module or a class using patch.multiple()
. Something like this should work for your case:
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()
When patch.multiple()
is used as a decorator, the mocks are passed into the decorated function by keyword, and a dictionary is returned when it's used as a context manager.