Skip to content
Advertisement

Python Mock Patch multiple methods in a class

Im trying to patch multiple methods in a class. Here is my simplified set up

Hook.py is defined as

JavaScript

HookTransfer.py defined as

JavaScript

I want to mock the methods get_key and get_value in the Hook class. The following works i.e. prints New_Key and New_Value

JavaScript

However this does not. It prints <MagicMock name='Hook().get_key()' id='4317706896'> and <MagicMock name='Hook().get_value()' id='4317826128'>

JavaScript

Intuitively it seems like the second one should work too but it doesnt. Could you help explain why it does not. I suspect it has something to do with “where to patch” but Im unable to get clarity.

Advertisement

Answer

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

  1. By mocking the return_value of mock1 (which returns mock2) mock_hook.return_value.get_key = mock.Mock(return_value="New_Key")
  2. 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.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement