Mocking in Python is a powerful technique used in unit testing to isolate the code being tested from its dependencies. It allows us to simulate the behavior of complex, real (non-deterministic) systems in order to test our code in isolation. In this article, we will discuss how to use mocks with unittest in Python for a hypothetical InvoicesAPI
class that interacts with an external HTTP service.
Table of Contents
The InvoicesAPI Class
Let’s assume we have the following simple InvoicesAPI
class:
class InvoicesAPI:
def __init__(self, http_client):
self.http_client = http_client
def get_invoices(self, search_params):
response = self.http_client.get('/api/invoices', params=search_params)
return response.json()
This class uses an HttpClient
to make HTTP requests and retrieve invoices based on the provided search parameters. The actual implementation of this class might involve more complex logic, but for simplicity’s sake, let’s assume it only makes a GET request with the given search parameters.
Mocking HttpClient
To test InvoicesAPI
without actually making HTTP requests to an external service, we can use Python’s built-in unittest.mock
module. This module provides a way to replace parts of your system under test and make assertions about how they have been used.
Here is an example of how you might write a unit test for the InvoicesAPI
class using mocks:
import unittest
from unittest.mock import Mock
from invoices_api import InvoicesAPI
class TestInvoicesAPI(unittest.TestCase):
def setUp(self):
self.http_client = Mock()
self.invoices_api = InvoicesAPI(self.http_client)
def test_get_invoices(self):
# Arrange
search_params = {'customer': 'John Doe'}
expected_response = [{'invoice_id': 1}, {'invoice_id': 2}]
self.http_client.get.return_value.json.return_value = expected_response
# Act
result = self.invoices_api.get_invoices(search_params)
# Assert
self.http_client.get.assert_called_once_with('/api/invoices', params=search_params)
self.assertEqual(result, expected_response)
In this test, we first create a Mock
object for the HttpClient
and pass it to our InvoicesAPI
instance in the setUp
method.
We arrange by setting up the expected response from the HTTP request and the search parameters for our test case. In the act step, we call the get_invoices
method of our InvoicesAPI
instance. Finally, in the assert step, we verify that the mocked HttpClient
was called with the correct arguments and returned the expected response.
Conclusion
Mocking is a powerful tool for unit testing in Python. It allows us to isolate our code from its dependencies and simulate their behavior. By using mocks, we can write tests that are fast, reliable, and easy to maintain. In this article, we discussed how to use the unittest.mock
module to mock out dependencies in a hypothetical InvoicesAPI
class.