Python > Testing in Python > Mocking and Patching > Using the `unittest.mock` module
Mocking a Class with `unittest.mock.patch.object`
This snippet demonstrates how to use unittest.mock.patch.object
to replace a method of a class with a mock during testing. This technique is especially useful when you want to test the interaction of a class with one of its own methods or when the class is passed as an argument.
Code Snippet
This code defines a class The test case ProductionClass
with a method method_to_mock
which is meant to represent a complicated task. another_method
calls method_to_mock
. function_under_test
takes an instance of ProductionClass
as an argument and calls another_method
on it.TestProductionClass
uses @patch.object(ProductionClass, 'method_to_mock')
to replace method_to_mock
with a mock object. We set the return_value
of the mock and then call function_under_test
. Finally, assertions check if the returned result is correct and verify if the mock was called with the appropriate argument.
import unittest
from unittest.mock import patch
class ProductionClass:
def method_to_mock(self, arg):
# Assume this method performs a complex calculation or interacts
# with external resources.
return f"Real result with {arg}"
def another_method(self):
return self.method_to_mock("default")
def function_under_test(obj):
return obj.another_method()
class TestProductionClass(unittest.TestCase):
@patch.object(ProductionClass, 'method_to_mock')
def test_function_under_test(self, mock_method):
mock_method.return_value = "Mocked result"
instance = ProductionClass()
result = function_under_test(instance)
self.assertEqual(result, "Mocked result")
mock_method.assert_called_with("default") #verify the arguments passed
if __name__ == '__main__':
unittest.main()
Concepts Behind the Snippet
Patching Objects: Context Management: patch.object
is used to replace specific attributes (methods in this case) of a given object with a mock. This is useful when you want to control the behavior of a particular method without affecting other parts of the class or its instances.patch.object
returns a context manager, allowing the mock to be active only within a specific code block (e.g., the test method). It automatically restores the original method after the block is executed.
Real-Life Use Case
Consider a class that interacts with a file system or a network resource. You can mock the methods responsible for these interactions to test other functionalities of the class without actually reading from or writing to files or making network requests. This ensures that the test remains fast, reliable, and avoids potential side effects.
Best Practices
patch.object
to mock only the methods that are relevant to the test. This avoids unnecessary mocking and reduces the risk of breaking other parts of the code.assert_called
, assert_called_with
, and other assertion methods to ensure that the mocked method is called with the expected arguments.stop()
on the patcher.
Interview Tip
Be ready to explain the advantages of using patch.object
over other mocking techniques, especially when testing class methods. Highlight its ability to target specific methods and its ease of use with context managers.
When to Use `patch.object`
Use patch.object
when:
Pros
Cons
FAQ
-
What happens if the patched object/method doesn't exist?
If the object or method specified inpatch.object
doesn't exist, the patcher will raise anAttributeError
. -
How do I mock multiple methods of the same class?
You can use multiple@patch.object
decorators, one for each method you want to mock.