How can I use Python's `patch.object` to change the return value of a method called within another method in my unit tests?

How can I use Python’s patch.object to change the return value of a method called within another method in my unit tests?

I have a scenario where one method calls another, and I want to mock the return value of the inner method in all the methods I’m testing. For example:

class Foo:
    def method_1(self):
        results = self.uses_some_other_method()
    
    def method_n(self):
        results = self.uses_some_other_method()

In my unit test, I want to mock uses_some_other_method() so that it always returns a specified value every time it’s called within any method of the Foo class. How can I achieve this using @patch.object in my test?

I’m looking for a way to mock the method’s return value across different method calls within the same class using Python patch object.

Hi Keerti,

If the method you’re testing is calling a function that is indirectly imported, you can use patch to mock it.

Example:

# foo.py
def some_fn():
    return 'some_fn'

class Foo(object):
    def method_1(self):
        return some_fn()

# bar.py
import foo
class Bar(object):
    def method_2(self):
        tmp = foo.Foo()
        return tmp.method_1()

# test_case_1.py
import bar
from mock import patch

@patch('foo.some_fn')
def test_bar(mock_some_fn):
    mock_some_fn.return_value = 'test-val-1'
    tmp = bar.Bar()
    assert tmp.method_2() == 'test-val-1'
    mock_some_fn.return_value = 'test-val-2'
    assert tmp.method_2() == 'test-val-2'

In this case, we mock some_fn using patch, and the mock will be automatically removed after the test function completes.

If you are directly importing the module that contains the method you want to mock, you can use patch.object.

Example:

# test_case_2.py
import foo
from mock import patch

@patch.object(foo, 'some_fn')
def test_foo(test_some_fn):
    test_some_fn.return_value = 'test-val-1'
    tmp = foo.Foo()
    assert tmp.method_1() == 'test-val-1'
    test_some_fn.return_value = 'test-val-2'
    assert tmp.method_1() == 'test-val-2'

Here, patch.object is used to mock some_fn directly in the foo module. The mock is also removed once the test completes.

If you need to mock multiple functions at the same time, you can stack patch.object decorators.

Example:

# test_case_3.py
import foo
from mock import patch

@patch.object(foo, 'some_fn')
@patch.object(foo, 'other_fn')
def test_foo(test_other_fn, test_some_fn):
    test_some_fn.return_value = 'test-val-1'
    test_other_fn.return_value = 'test-val-2'
    tmp = foo.Foo()
    assert tmp.method_1() == 'test-val-1'
    assert tmp.method_1() == 'test-val-2'

In this example, we mock both some_fn and other_fn using multiple decorators. Note that the order of decorators matters — the decorator closer to the function definition is passed later in the parameter list.