Python > Testing in Python > Mocking and Patching > Using the `unittest.mock` module
Mocking a Function with `unittest.mock.patch`
This example demonstrates how to use unittest.mock.patch
to replace a function with a mock object during testing. This allows you to isolate the code being tested from its dependencies and control the behavior of those dependencies.
Code Snippet
This code defines a function The get_data_from_api
that simulates fetching data from an external API. The process_data
function calls get_data_from_api
and processes the result.TestProcessData
class uses unittest.TestCase
to define a test case. The @patch
decorator from unittest.mock
replaces get_data_from_api
with a Mock
object for the duration of the test. Inside the test method, we configure the Mock
object's return_value
. We then call process_data
, which now uses the mocked get_data_from_api
. Finally, we use assertions to verify that the mock was called and that the result of process_data
is as expected. mock_get_data_from_api.assert_called_once()
is used to verify that the mocked function was called only once during the test.
import unittest
from unittest.mock import patch
# Assume this function makes an external API call
def get_data_from_api():
# In reality, this would be an API call
return "Real API data"
# Function to test
def process_data():
data = get_data_from_api()
return f"Processed: {data}"
class TestProcessData(unittest.TestCase):
@patch('__main__.get_data_from_api') # Replace get_data_from_api with a mock
def test_process_data(self, mock_get_data_from_api):
# Configure the mock's return value
mock_get_data_from_api.return_value = "Mocked API data"
# Call the function being tested
result = process_data()
# Assert that the mock was called
mock_get_data_from_api.assert_called_once()
# Assert that the function returns the expected value
self.assertEqual(result, "Processed: Mocked API data")
if __name__ == '__main__':
unittest.main()
Concepts Behind the Snippet
Mocking: Mocking involves replacing real objects with controlled substitutes (mocks) that can be easily configured and inspected. This helps isolate the unit being tested from its dependencies. Patching: Patching is a technique used to temporarily replace parts of your code with mocks during testing. The unittest.mock.patch
decorator is a convenient way to achieve this.unittest.mock.Mock
: The Mock
class is the core class for creating mock objects. It allows you to define return values, side effects, and track method calls.
Real-Life Use Case
Imagine you're testing a function that relies on a database connection. Instead of connecting to a real database during testing (which can be slow, unreliable, and potentially modify data), you can mock the database connection object. This allows you to simulate different database responses and test your function's behavior under various conditions without actually interacting with the database. Another common use case is mocking external API calls, as shown in the code snippet. This prevents tests from being dependent on the availability and behavior of external services.
Best Practices
assert_called
, assert_called_once
, assert_called_with
, and other assertion methods to verify that your code interacts with the mocks as expected.
Interview Tip
Be prepared to explain the difference between mocking and stubbing. A mock is an object that replaces a real dependency and allows you to verify how it was used. A stub provides pre-programmed responses to method calls and is primarily used to control the state of the dependency. Also, be ready to discuss the benefits of mocking in terms of test isolation, speed, and determinism.
When to Use Mocking
Use mocking when:
Alternatives
Alternatives to unittest.mock
include:
pytest-mock
: A pytest plugin that provides convenient mocking functionality.doublex
: A powerful mocking framework with a more expressive API.
Pros
Cons
FAQ
-
Why should I mock?
Mocking allows you to isolate the unit of code you're testing, making your tests faster, more reliable, and independent of external factors. -
What's the difference between a mock and a stub?
A mock is used to verify interactions (e.g., that a method was called with specific arguments), while a stub simply provides pre-programmed responses.