To do that you can mock the class function with the @patch like that

from mock import patch

# Our class to test
class FooObject():
    def update(self, obj):
        print obj

# Mock the update method
@patch.object(FooObject, 'update')
def test(mock1):
    # test that the update method is actually mocked
    assert FooObject.update is mock1
    foo = FooObject()
    foo.update('foo')
    return mock1

# Test if the mocked update method was called with 'foo' parameter
mock1 = test()
mock1.assert_called_once_with('foo')

You can even mock more functions like that:

from mock import patch

class FooObject():
    def update(self, obj):
        print obj

    def restore(self, obj):
        print obj

@patch.object(FooObject, 'restore')
@patch.object(FooObject, 'update')
def test(mock1, mock2):
    assert FooObject.update is mock1
    assert FooObject.restore is mock2
    foo = FooObject()
    foo.update('foo')
    foo.restore('bar')
    return mock1, mock2

mock1, mock2 = test()
mock1.assert_called_once_with('foo')
mock2.assert_called_once_with('bar')
Answer from Tim Rijavec on Stack Overflow
Top answer
1 of 4
8

In the end I used Python's mock, which allows me to override complicated_function without having to adjust the original code in any way.

Here is the original script, and note that complicated_function is not passed in to my_loopy_function as an 'action_function' parameter (which was what I tried in my earlier solutions):

// my_script.py

def my_loopy_function():
    aggregate_value = 0
    for x in range(10):
        aggregate_value = aggregate_value + complicated_function(x)
    return aggregate_value

def complicated_function(x):
    a = do()
    b = something()
    c = complicated()
    return a + b + c

and here is the script I am using to test it:

// test_my_script.py

import unittest
import mock
from my_script import my_loopy_function

class TestMyModule(unittest.TestCase):
    @mock.patch('my_script.complicated_function')
    def test_1(self, mocked):
        mocked.return_value = 1
        self.assertEqual(10, my_loopy_function())

This works just as I had wanted:

  1. I am able to substitute functions with a simpler version of themselves that I can more easily test,
  2. I do not need to alter my original code in any way (such as I was trying -- which was effectively by passing in function pointers), the mock module gives me post-coding access to the innards.

Thanks to austin for his suggestion to use mock. BTW I am using Python 2.7 and therefore used the pip-installable mock from PyPI.

2 of 4
3

Don't try to override complicated_function with action_function, just use complicated_function as the default action_function:

def my_loopy_function(action_function=complicated_function):
    aggregate_value = 0
    for x in range(10):
        aggregate_value = aggregate_value + action_function(x)
    return aggregate_value
🌐
Skybert
skybert.net › python › mocking-classes-and-overriding-methods-in-python
Mocking classes and overriding methods in Python | skybert.net
November 7, 2018 - import types import unittest.mock class ExploringMocking(unittest.TestCase): def test_mocking_a_class(self): waterfall = unittest.mock.create_autospec(Waterfall) waterfall.height_in_feet = types.MethodType( self.my_height_func, self ) assert waterfall.height_in_feet() == 10 def my_height_func(self, ref): return 10 · The essential bit here is the types.MethodType which is what you need to do when overriding the method on a class instance.
🌐
Python
docs.python.org › 3 › library › unittest.mock-examples.html
unittest.mock — getting started
Mock (in all its flavours) uses a method called _get_child_mock to create these “sub-mocks” for attributes and return values. You can prevent your subclass being used for attributes by overriding this method.
🌐
GitHub
github.com › python › cpython › issues › 122726
Mocked value at method level not overriding class-level mock in unittest · Issue #122726 · python/cpython
August 6, 2024 - Create a test class with a class-level mock using @mock.patch. Add a method-level mock to one of the test methods to override the class-level mock.
🌐
GitHub
github.com › fastapi › fastapi › discussions › 7920
How do I mock or override classes and methods for unittests? · fastapi/fastapi · Discussion #7920
I managed to get my tests running again by installing the great package pytest-mock. I also realized the reason for my mock failing was a case of what gets initialized when so I made it lazy and that fixed things.
Author: fastapi
Top answer
1 of 2
3

Yes! You can leverage the setUp/tearDown methods of the unittest.TestCase and the fact that unittest.mock.patch in its "pure" form (i.e. not as context manager or decorator) returns a "patcher" object that has start/stop methods to control when exactly it should do its magic.

You can call on the patcher to start inside setUp and to stop inside tearDown and if you keep a reference to it in an attribute of your test case, you can easily stop it manually in selected test methods. Here is a full working example:

from unittest import TestCase
from unittest.mock import patch


class Foo:
    @staticmethod
    def bar() -> int:
        return 1


class TestMyThing(TestCase):
    def setUp(self) -> None:
        self.foo_bar_patcher = patch.object(Foo, "bar", return_value=42)
        self.mock_foo_bar = self.foo_bar_patcher.start()
        super().setUp()

    def tearDown(self) -> None:
        self.foo_bar_patcher.stop()
        super().tearDown()

    def test_a(self):
        self.assertEqual(42, Foo.bar())

    def test_b(self):
        self.assertEqual(42, Foo.bar())

    def test_c(self):
        self.assertEqual(42, Foo.bar())

    def test_d(self):
        self.foo_bar_patcher.stop()
        self.assertEqual(1, Foo.bar())

This patching behavior is the same, regardless of the different variations like patch.object (which I used here), patch.multiple etc.

Note that for this example it is not necessary to keep a reference to the actual MagicMock instance generated by the patcher in an attribute, like I did with mock_foo_bar. I just usually do that because I often want to check something against the mock instance in my test methods.

It is worth mentioning that you can also use setUpClass/tearDownClass for this, but then you need to be careful with re-starting the patch, if you stop it because those methods are (as the name implies) only called once for each test case, whereas setUp/tearDown are called once before/after each test method.

PS: The default implementations of setUp/tearDown on TestCase do nothing, but it is still good practice IMO to make a habit of calling the superclass' method, unless you deliberately want to omit that call.

2 of 2
1

While accepted answer is perfectly fine, I'd go for approach which keeps decorator for the class and uses context managers for methods in which you want to override a mock, see sample code below:

@mock.patch("foo", bar)
class TestMyThing(TestCase):
  def test_A(self):
    assert something

  def test_B(self):
    assert something

  def test_C(self):
    assert something

  def test_D(self):
    with patch('foo', baz):
        assert something

This achieves your goal, as context manager mock is applied inside of a test function, so it happens after applying the class decorator mock and therefore it effectively overrides class decorator mock. Also, I think it's simpler and it requires less code, especially if you have no other reason to implement setUp() and tearDown() methods.

🌐
Medium
yeraydiazdiaz.medium.com › what-the-mock-cheatsheet-mocking-in-python-6a71db997832
What the mock? — A cheatsheet for mocking in Python | by Yeray Diaz | Medium
August 19, 2019 - This is the default behaviour, but it can be overridden in different ways. For example you can assign a value to an attribute in the Mock by: Assign it directly, like you’d do with any Python object. Use the configure_mock method on an instance.
Find elsewhere
Top answer
1 of 1
44

Well, turns out that a good night sleep and a cold shower made me rethink the whole issue. I'm still very new to the concept of mocking, so it still hasn't sunk in quite right.

The thing is, there's no need to override the patch to a mocked object. It's a mocked object and that means I can make it do anything. So my first try was:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         method_to_patch.return_value = 2
         (....)

That worked, but had the side effect of changing the return value for all following tests. So then I tried:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         method_to_patch.return_value = 2
         (....)
         method_to_patch.return_value = 1

And it worked like a charm. But seemed like too much code. So then I went the down the road of context management, like this:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         with mock.patch('method_to_patch', mock.Mock(return_value=2):
             (....)

I think it seems clearer and more concise.

About the order in which the patch decorators were being applied, it's actually the correct order. Just like stacked decorators are applied from the bottom up, a method decorator is supposed to be called before the class decorator. I guess it makes sense, I was just expecting the opposite behavior.

Anyway, I hope this help some poor newbie soul like mine in the future.

🌐
Python
docs.python.org › 3 › library › unittest.mock.html
unittest.mock — mock object library
The Mock classes have support for mocking magic methods. See magic methods for the full details. The mock classes and the patch() decorators all take arbitrary keyword arguments for configuration. For the patch() decorators the keywords are passed to the constructor of the mock being created.
🌐
Readthedocs
testfixtures.readthedocs.io › en › latest › mocking.html
Mocking out objects and methods - testfixtures 11.0.0 documentation
It may also mean replacing chunks of complex functionality that aren’t the subject of the test with mock objects that allow you to check that the mocked out functionality is being used as expected. Python has a standard mock implementation in the form of unittest.mock which is also available ...
🌐
pytest
docs.pytest.org › en › 7.1.x › how-to › monkeypatch.html
How to monkeypatch/mock modules and environments — pytest documentation
The mock of r needs a .json() method which returns a dictionary. This can be done in our test file by defining a class to represent r. # contents of test_app.py, a simple test for our API retrieval # import requests for the purposes of monkeypatching import requests # our app.py that includes the get_json() function # this is the previous code block example import app # custom class to be the mock return value # will override the requests.Response returned from requests.get class MockResponse: # mock json() method always returns a specific testing dictionary @staticmethod def json(): return {"mock_key": "mock_response"} def test_get_json(monkeypatch): # Any arguments may be passed and mock_get() will always return our # mocked object, which only has the .json() method.
Top answer
1 of 1
1

Apart from the multiple errors in the example code I wrote up off the top of my head at the cafe ...

The problem was (mostly) that I was using return_value instead of side_effect to 'replace' the patched class with my own subclass.

My need, re-stated perhaps more clearly now, is to override a single method, set_some_stuff, in a class within the unit under test (UUT) but without mocking the class.

The method issues several 'self.foo = bar' statements, which I want to change for testing purposes. Thus, mocking the method's (unused) return value is not enough ... and patch.object seems to lose class context, "'self' unknown" or the like.

Finally, here is the working code, doing what I need ...

import unittest
import mock

class SetupClass(object):
    def set_some_stuff(self):
        data_list = ['data not available', 'on test_platform'] # CRASH!
        self.something = data_list[0]
        self.something_else = data_list[1]

class UUT:
    def __init__(self):
        self.config = SetupClass()
        self.config.set_some_stuff()
        assert self.config.something == 'foo' # <-- used to crash before here ...
        self.got_here = True # ... but now the override method from
                             # WedgeClass is being used! :=)

"""
Subclass the original class, overriding just the method in question.  Then set
the subclass as the side_effect of the patched original, effectively replacing it.
"""
class WedgeClass(SetupClass):
    def set_some_stuff(self):
        self.something = 'foo'
        pass # I'm a Python newbie, in too deep

class UnitTests(unittest.TestCase):

    @mock.patch(__module__+'.SetupClass')
    def test_UUT(self, mock1):
        wedge_class = WedgeClass()
        mock1.side_effect = WedgeClass # <--- Ureka! 'side_effect' not 'return_value' was the ley!

        uut = UUT()
        self.assertTrue(uut.got_here)
Top answer
1 of 4
11

I think you are looking for monkey patching (means changing classes/modules dynamically while running). This way you don't need to overwrite the class A and use inheritance as suggested by other comments - you said you don't want that, so try this solution:

import some_class  # import like this or will not work (cos of namespaces)

def new_some_function():
   print("new_some_function")

if __name__ == '__main__':
    # Import and use like this, other ways of import will not work.
    # Because other way imports method to your namespace and then change it in your namespace,
    # but you need to change it in the original namespace
    some_class.some_function = new_some_function

That way replace the original method and even other classes will use it then. Be careful, if the original method is a class/instance method, you need to create new function with proper params, like this:

def new_some_function(self):
    # for instance methods, you may add other args, but 'self' is important

def new_some_function(cls):
    # for class methods, you may add other args, but 'cls' is important
2 of 4
2

You provide very little information about your use case here. As one of the comments points out, this might be a case for inheritance. If you are in a testing context, you may not want to use inheritance though, but you might rather want to use a mock-object.

Here is the inheritance version:

from some_library import A

def new_some_function():
    print("new_some_function")

class B(A):
    def xxx(self):
        new_some_function()

if __name__ == '__main__':
    a = B()
    a.xxx()

Note, how class B derives from class A through the class B(A) statement. This way, class B inherits all functionality from A and the definition of class B only consists of the parts where B differs from A. In your example, that is the fact that the xxx method should call new_some_function instead of some_function.

Here is the mock version:

from unittest import mock
from some_library import A

def new_some_function():
    print("new_some_function")

if __name__ == '__main__':
    with mock.patch('some_library.some_function') as mock_some_function:
        mock_some_function.side_effect = new_some_function
        a = A()
        a.xxx()

As mentioned above this approach is mostly useful if you are in a testing context and if some_function does something costly and/or unpredictable. In order to test code that involves a call to some_function, you may temporarily want to replace some_function by something else, that is cheap to call and behaves in a predictable way. In fact, for this scenario, replacing some_function by new_some_function might even be more than what is actually needed. Maybe, you just want an empty hull that can be called and that always returns the same value (instead of the side_effect line, you can specify a constant .return_value in the above code example). One of the key functionalities of mock objects is that you can later check if that function has been called. If testing is your use case, I would very much recommend looking at the documentation of the python mock module.

Note that the example uses the mock.patch context manager. This means that within the managed context (i.e. the block inside the with-statement) some_library.some_function is replaced by a mock object, but once you leave the managed context, the original functionality is put back in place.

🌐
Python
bugs.python.org › issue42019
Issue 42019: Override MagicMock special methods - Python tracker
This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/86185
🌐
pytest
docs.pytest.org › en › stable › how-to › monkeypatch.html
How to monkeypatch/mock modules and environments - pytest documentation
The mock of r needs a .json() method which returns a dictionary. This can be done in our test file by defining a class to represent r. # contents of test_app.py, a simple test for our API retrieval # import requests for the purposes of monkeypatching import requests # our app.py that includes the get_json() function # this is the previous code block example import app # custom class to be the mock return value # will override the requests.Response returned from requests.get class MockResponse: # mock json() method always returns a specific testing dictionary @staticmethod def json(): return {"mock_key": "mock_response"} def test_get_json(monkeypatch): # Any arguments may be passed and mock_get() will always return our # mocked object, which only has the .json() method.