Find Out If a Function has been Called
Memoization functions have been around since the 1960s. In python you can use them as decorators on your example() function.
The standard memoization function looks something like this:
def memoize(func):
memo = {}
def wrapper(*args):
if not args in memo:
memo[args] = func(*args)
return memo[args]
return wrapper
and you decorate your function like this:
@memoize
def example():
pass
In python3.2, you can use the functools.lru_cache instead of the memoziation function.
import functools
@functools.lru_cache(maxsize=None)
def example():
pass
We can use mock.Mock
from unittest import mock
def check_called(func):
return mock.Mock(side_effect=func)
@check_called
def summator(a, b):
print(a + b)
summator(1, 3)
summator.assert_called()
assert summator.called == True
assert summator.call_count > 0
summator.assert_called_with(1, 3)
summator.assert_called_with(1, 5) # error
# AssertionError: Expected call: mock(1, 5)
# Actual call: mock(1, 3)
If it's OK for the function to know its own name, you can use a function attribute:
def example():
example.has_been_called = True
pass
example.has_been_called = False
example()
#Actual Code!:
if example.has_been_called:
print("foo bar")
You could also use a decorator to set the attribute:
import functools
def trackcalls(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
wrapper.has_been_called = True
return func(*args, **kwargs)
wrapper.has_been_called = False
return wrapper
@trackcalls
def example():
pass
example()
#Actual Code!:
if example.has_been_called:
print("foo bar")
A minimal example using unittest.mock.Mock
from the standard library:
from unittest.mock import Mock
def example():
pass
example_mock = Mock(side_effect=example)
example_mock()
#Pseudocode:
if example_mock.called:
print("foo bar")
Console output after running the script:
foo bar
This approach is nice because it doesn't require you to modify the example
function itself, which is useful if you want to perform this check in some unit-testing code, without modifying the source code itself (EG to store a has_been_called
attribute, or wrap the function in a decorator).
Explanation
As described in the documentation for the unittest.mock.Mock
class, the side_effect
argument to the Mock()
constructor specifies "a function to be called whenever the Mock is called".
The Mock.called
attribute specifies "a boolean representing whether or not the mock object has been called".
The Mock
class has other attributes you may find useful, EG:
call_count
: An integer telling you how many times the mock object has been called
call_args
: This is either None (if the mock hasn’t been called), or the arguments that the mock was last called with
call_args_list
: This is a list of all the calls made to the mock object in sequence (so the length of the list is the number of times it has been called). Before any calls have been made it is an empty list
The Mock
class also has convenient methods for making assert statements based on how many times a Mock
object was called, and what arguments it was called with, EG:
assert_called_once_with(*args, **kwargs)
: Assert that the mock was called exactly once and that that call was with the specified arguments