Python tutorials > Testing > Mocking > How to assert mock calls?
How to assert mock calls?
Mocking is a powerful technique in Python testing that allows you to isolate the unit under test by replacing its dependencies with controlled substitutes, called mocks. Asserting mock calls is crucial to verify that your code interacts with these dependencies as expected. This tutorial will guide you through various ways to assert mock calls using the unittest.mock
library.
Basic Assertion: assert_called()
The assert_called()
method simply checks if the mock object was called at least once. In the example, we create a mock dependency, pass it to my_function
, and then assert that the do_something
method of the mock was called. This is the most basic assertion you can make on a mock.
import unittest
from unittest.mock import Mock
def my_function(dependency):
dependency.do_something(1, 2)
class TestMyFunction(unittest.TestCase):
def test_my_function_calls_dependency(self):
mock_dependency = Mock()
my_function(mock_dependency)
mock_dependency.do_something.assert_called()
Checking Call Arguments: assert_called_with()
The assert_called_with()
method verifies that the mock was called exactly once with the specified arguments. In this example, we assert that do_something
was called with the arguments 1
and 2
.
import unittest
from unittest.mock import Mock
def my_function(dependency):
dependency.do_something(1, 2)
class TestMyFunction(unittest.TestCase):
def test_my_function_calls_dependency_with_correct_arguments(self):
mock_dependency = Mock()
my_function(mock_dependency)
mock_dependency.do_something.assert_called_with(1, 2)
Checking Call Order and Multiple Calls: assert_has_calls()
and call
The assert_has_calls()
method checks if the mock was called with a sequence of specific calls in the given order. The call
object represents a single call to the mock. This example verifies that do_something
was called first with 1
and then with 2
.
import unittest
from unittest.mock import Mock, call
def my_function(dependency):
dependency.do_something(1)
dependency.do_something(2)
class TestMyFunction(unittest.TestCase):
def test_my_function_calls_dependency_multiple_times(self):
mock_dependency = Mock()
my_function(mock_dependency)
mock_dependency.do_something.assert_has_calls([call(1), call(2)])
Checking Any Call: any
The any_
object can be used as a placeholder argument when you don't care about the specific value of that argument. This example asserts that do_something
was called with 1
as the first argument and any value as the second argument.
import unittest
from unittest.mock import Mock, any_
def my_function(dependency):
dependency.do_something(1, 'hello')
class TestMyFunction(unittest.TestCase):
def test_my_function_calls_dependency_with_any(self):
mock_dependency = Mock()
my_function(mock_dependency)
mock_dependency.do_something.assert_called_with(1, any_)
Checking the Most Recent Call: assert_called_once_with()
The assert_called_once_with()
method asserts that the mock was called exactly once with the specified arguments. It's different from assert_called_with
if you only want to ensure that the function was only called once. The previous calls won't make the validation fail. In the code, an AssertionError
is raised because do_something
was called twice.
import unittest
from unittest.mock import Mock
def my_function(dependency):
dependency.do_something(1)
dependency.do_something(2)
class TestMyFunction(unittest.TestCase):
def test_my_function_calls_dependency_once_with(self):
mock_dependency = Mock()
my_function(mock_dependency)
with self.assertRaises(AssertionError):
mock_dependency.do_something.assert_called_once_with(1)
Concepts Behind the Snippet
Mocking is a testing technique that replaces real dependencies of a unit under test with controlled substitutes (mocks). Assertions on mock calls verify that the unit under test interacts with its dependencies as expected. These assertions provide confidence that the code is functioning correctly by isolating and testing its interactions with external components.
Real-Life Use Case
Consider a scenario where you're testing a function process_data
that interacts with an external API client. You can mock the API client to control its behavior (e.g., return a success or failure response) and then assert that the process_data
function calls the API client's methods (e.g., send_data
, log_success
, log_failure
) with the correct arguments based on the API response.
import unittest
from unittest.mock import Mock
def process_data(api_client, data):
result = api_client.send_data(data)
if result['status'] == 'success':
api_client.log_success(data)
else:
api_client.log_failure(data)
class TestProcessData(unittest.TestCase):
def test_process_data_success(self):
mock_api_client = Mock()
mock_api_client.send_data.return_value = {'status': 'success'}
process_data(mock_api_client, {'key': 'value'})
mock_api_client.send_data.assert_called_with({'key': 'value'})
mock_api_client.log_success.assert_called_with({'key': 'value'})
mock_api_client.log_failure.assert_not_called()
def test_process_data_failure(self):
mock_api_client = Mock()
mock_api_client.send_data.return_value = {'status': 'failure'}
process_data(mock_api_client, {'key': 'value'})
mock_api_client.send_data.assert_called_with({'key': 'value'})
mock_api_client.log_success.assert_not_called()
mock_api_client.log_failure.assert_called_with({'key': 'value'})
Best Practices
assert_called()
when you can be more precise with assert_called_with()
or assert_has_calls()
.
Interview Tip
When discussing mocking in interviews, be prepared to explain:
When to Use Mock Call Assertions
Use mock call assertions whenever you need to verify that your code interacts correctly with its dependencies. This is especially important when dealing with:
Alternatives
While unittest.mock
is the standard library's mocking framework, other popular options exist:
Pros
Cons
FAQ
-
What happens if I use
assert_called_with
when the mock was never called?
AnAssertionError
will be raised, indicating that the mock was not called with the specified arguments. -
Can I check the arguments passed to a mock when the order of arguments is not important?
Yes, you can usecall_args
to get the arguments as a tuple or dictionary, and then use standard Python assertions to check the arguments regardless of order. -
How can I assert that a mock method was not called?
You can useassert_not_called()
. For example:mock_object.method.assert_not_called()