Use unittest.mock to Monitor Calls
In this step, we'll explore how to use the unittest.mock
module to monitor function calls. The unittest.mock
module is a powerful tool for testing and debugging, and it provides a convenient way to track function invocations, arguments, and return values.
Let's continue with the greet
function from the previous steps. We'll use unittest.mock
to monitor the calls to greet
.
Modify the my_function.py
file in the ~/project
directory to include the following code:
## ~/project/my_function.py
from unittest import mock
def greet(name):
"""This function greets the person passed in as a parameter."""
print(f"Hello, {name}!")
## Create a mock object for the greet function
mock_greet = mock.Mock(wraps=greet)
## Example usage
mock_greet("Alice")
mock_greet("Bob")
## Print the number of times the function was called
print(f"The greet function was called {mock_greet.call_count} times.")
## Print the arguments the function was called with
print(f"The calls were: {mock_greet.call_args_list}")
In this code:
- We import the
mock
module from unittest
.
- We create a
mock.Mock
object that wraps the greet
function. The wraps
argument tells the mock object to call the original greet
function when it's called.
- We then call the
mock_greet
object instead of the original greet
function.
- Finally, we use the
call_count
and call_args_list
attributes of the mock object to get information about the function calls.
Run the script again using the same command:
python ~/project/my_function.py
You should see output similar to this:
Hello, Alice!
Hello, Bob!
The greet function was called 2 times.
The calls were: [call('Alice'), call('Bob')]
This output shows that the greet
function was called twice, and it also shows the arguments that were passed to the function in each call.
Now, let's examine the call_args_list
more closely. It's a list of call
objects, each representing a single call to the mocked function. You can access the arguments of each call using the args
and kwargs
attributes of the call
object.
For example, let's modify the code to print the arguments of the first call:
## ~/project/my_function.py
from unittest import mock
def greet(name):
"""This function greets the person passed in as a parameter."""
print(f"Hello, {name}!")
## Create a mock object for the greet function
mock_greet = mock.Mock(wraps=greet)
## Example usage
mock_greet("Alice")
mock_greet("Bob")
## Print the number of times the function was called
print(f"The greet function was called {mock_greet.call_count} times.")
## Print the arguments the function was called with
print(f"The calls were: {mock_greet.call_args_list}")
## Print the arguments of the first call
if mock_greet.call_args_list:
print(f"The arguments of the first call were: {mock_greet.call_args_list[0].args}")
Run the script again:
python ~/project/my_function.py
You should see output similar to this:
Hello, Alice!
Hello, Bob!
The greet function was called 2 times.
The calls were: [call('Alice'), call('Bob')]
The arguments of the first call were: ('Alice',)
This output shows that the first call to greet
was made with the argument "Alice"
.
The unittest.mock
module provides a powerful and flexible way to monitor function calls in Python. It's a valuable tool for testing, debugging, and performance analysis.