How should I mock patch.object() a function in a module?

How should I mock patch.object() a function in a module?
home_dir() is what I want to test.

my_info.py

from pathlib import Path

def home_dir():
    return str(Path.home())


if __name__ == "__main__":
    print(home_dir())

test_my_info.py

from unittest import mock
import my_info

def test_my_home_returns_correct_value():
    with mock.patch.object(my_info, "home_dir", autospec=True) as mock_home_dir:
        my_info.home_dir.return_value = "/users/fake_user" # 1.1
        # mock_home_dir.return_value = "/users/fake_user" # 1.2


        value = my_info.home_dir() # 2.1
        # value = my_info.home_dir.return_value # 2.2
        # value = mock_home_dir() # 2.3
        # value = mock_home_dir.return_value # 2.4


        assert value == "/users/fake_user"

For 1.x
should I use my_info.home_dir.return_value or mock_home_dir.return_value to set the return value?

For 2.x
should I use my_info.home_dir or mock_home_dir to retrieve the return value?
should I use () or return_value to retrieve the return value?

It is much more readable and meaningful to set the return value of the mock object mock_home_dir and call the mocked function with my_info.home_dir() as if it weren’t mocked because:

  • When you set a fake return value, you want to make it explicit that the fake value is set on a mock object. my_info.home_dir is normally not a mock object and does not normally have a return_value attribute so setting a fake value on it can look confusing.
  • When you call a mocked function, you want to call the original function variable because as a unit test it is all about trying code in ways it is normally written. Calling mock_home_dir() does not help test usage of the mocked function, while mock_home_dir.return_value and my_info.home_dir.return_value are simply retrieving the fake return values from the mock object and does not call the mocked function to help test it at all.
1 Like