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.objectdoesn't exist, the patcher will raise anAttributeError. -
How do I mock multiple methods of the same class?
You can use multiple@patch.objectdecorators, one for each method you want to mock.