Skip to main content

How to Use Assert Mock Library With Specific Arguments to Check Mock Calls for Testing

When using Python's unittest.mock library for testing, mocks stand in for real objects. A crucial part of testing with mocks is verifying that they were interacted with as expected, specifically, that they were called with the correct arguments.

This guide demonstrates how to use the various assertion methods provided by unittest.mock (assert_called_with, assert_called_once_with, assert_any_call, assert_has_calls) to check mock calls accurately.

Why Assert Mock Calls?

Mocks help isolate the unit under test by replacing its dependencies. Asserting mock calls ensures that your code interacts with these dependencies correctly: calling the right methods/functions with the appropriate data. This confirms the flow of logic and data transfer within your system.

assert_called_with(): Checking the Last Call

This method asserts that the most recent call to the mock was made with the exact arguments specified (both positional and keyword). It doesn't care about previous calls.

from unittest.mock import Mock
import unittest # Using unittest framework context for assertions

class MockCallTests(unittest.TestCase):

def test_assert_called_with_example(self):
mock_object = Mock(return_value=None)

# First call
print("Calling: mock_object('arg1', key='val1')")
mock_object('arg1', key='val1')

# ✅ Check the last (and only) call
mock_object.assert_called_with('arg1', key='val1')
print("Assertion 1 passed.\n")

# Second call with different arguments
print("Calling: mock_object('arg2')")
mock_object('arg2')

# ✅ Check the NEW last call
mock_object.assert_called_with('arg2')
print("Assertion 2 passed.\n")

# ⛔️ This now FAILS because the last call was mock_object('arg2'),
# not mock_object('arg1', key='val1')
print("Attempting assert_called_with for the first call again...")
with self.assertRaises(AssertionError) as cm:
mock_object.assert_called_with('arg1', key='val1')
print(f"Assertion 3 failed as expected: {cm.exception}")

# Helper to run the test case if script is run directly
# if __name__ == '__main__':
# unittest.main(argv=['first-arg-is-ignored'], exit=False)

assert_called_once_with(): Checking the Only Call

This method is stricter. It asserts two things simultaneously:

  1. The mock was called exactly once.
  2. That single call was made with the specified arguments.
from unittest.mock import Mock
import unittest

class MockCallOnceTests(unittest.TestCase):

def test_assert_called_once_with_example(self):
mock_object = Mock(return_value=None)

# Make the single call
print("Calling: mock_object('first and only', status=True)")
mock_object('first and only', status=True)

# ✅ Check the single call with correct args - This passes
mock_object.assert_called_once_with('first and only', status=True)
print("Assertion 1 (single call) passed.\n")

# Make a second call
print("Calling mock_object again...")
mock_object('second call')

# ⛔️ This now FAILS because the mock has been called more than once
print("Attempting assert_called_once_with again...")
with self.assertRaises(AssertionError) as cm:
mock_object.assert_called_once_with('first and only', status=True)
# The error message clearly states it was called more than once
print(f"Assertion 2 failed as expected: {cm.exception}")

# if __name__ == '__main__':
# unittest.main(argv=['first-arg-is-ignored'], exit=False)

assert_any_call(): Checking if Called Ever with Args

Use this when you want to verify if the mock was called with specific arguments at least once, regardless of other calls made before or after, or how many times it was called overall.

from unittest.mock import Mock
import unittest

class MockAnyCallTests(unittest.TestCase):

def test_assert_any_call_example(self):
mock_object = Mock(return_value=None)

print("Calling mock_object multiple times...")
mock_object(1, 2)
mock_object(name='Alice', age=30)
mock_object(1, 2) # Call with first args again
mock_object('final call')

# ✅ Check if it was *ever* called with (name='Alice', age=30) - Passes
mock_object.assert_any_call(name='Alice', age=30)
print("Assertion 1 (Alice) passed.")

# ✅ Check if it was *ever* called with (1, 2) - Passes
mock_object.assert_any_call(1, 2)
print("Assertion 2 (1, 2) passed.")

# ⛔️ This FAILS because it was never called with ('other', 99)
print("\nAttempting assert_any_call for ('other', 99)...")
with self.assertRaises(AssertionError) as cm:
mock_object.assert_any_call('other', 99)
print(f"Assertion 3 failed as expected: {cm.exception}")

# if __name__ == '__main__':
# unittest.main(argv=['first-arg-is-ignored'], exit=False)

assert_has_calls(): Checking a Sequence of Calls

This method asserts that the mock was called with a specific sequence of calls. The order usually matters unless specified otherwise. You need to use the unittest.mock.call object to construct the expected calls.

Checking Calls in Exact Order

By default, assert_has_calls checks if the provided sequence of calls exists as a sub-sequence within the mock's actual calls, in that exact order.

from unittest.mock import Mock, call # Import 'call'
import unittest

class MockHasCallsTests(unittest.TestCase):

def test_assert_has_calls_order_matters(self):
mock_object = Mock(return_value=None)

print("Making calls: A, B, C")
mock_object('A')
mock_object('B', status='pending')
mock_object('C')

# Define the expected sequence of calls using call() objects
expected_calls_in_order = [
call('A'),
call('B', status='pending'),
call('C')
]

# ✅ Check if this exact sequence occurred - Passes
mock_object.assert_has_calls(expected_calls_in_order)
print("Assertion 1 (correct order) passed.")

# Define a sequence with a different order
expected_calls_wrong_order = [
call('A'),
call('C'), # Order swapped with B
call('B', status='pending')
]

# ⛔️ This FAILS because the calls didn't happen in this specific sequence
print("\nAttempting assert_has_calls with wrong order...")
with self.assertRaises(AssertionError) as cm:
# any_order=False is the default
mock_object.assert_has_calls(expected_calls_wrong_order)
print(f"Assertion 2 failed as expected: {cm.exception}")

# It also checks for sub-sequences
partial_sequence = [call('A'), call('B', status='pending')]
mock_object.assert_has_calls(partial_sequence) # This passes
print("\nAssertion 3 (partial sequence) passed.")

# if __name__ == '__main__':
# unittest.main(argv=['first-arg-is-ignored'], exit=False)

Checking Calls in Any Order (any_order=True)

If the order doesn't matter, and you just want to ensure a set of specific calls happened at some point, add any_order=True.

from unittest.mock import Mock, call
import unittest

class MockHasCallsAnyOrderTests(unittest.TestCase):

def test_assert_has_calls_any_order(self):
mock_object = Mock(return_value=None)

print("Making calls: A, B, C")
mock_object('A')
mock_object('B', status='pending')
mock_object('C')

# Define the expected calls, order doesn't matter now
expected_calls_any_order = [
call('C'),
call('A'),
call('B', status='pending')
]

# ✅ Check if these calls occurred, regardless of order - Passes
mock_object.assert_has_calls(expected_calls_any_order, any_order=True)
print("Assertion 1 (any_order=True) passed.")

# ⛔️ Still FAILS if one of the expected calls is missing
missing_call_any_order = [
call('A'),
call('X') # This call never happened
]
print("\nAttempting assert_has_calls with missing call (any_order=True)...")
with self.assertRaises(AssertionError) as cm:
mock_object.assert_has_calls(missing_call_any_order, any_order=True)
print(f"Assertion 2 failed as expected: {cm.exception}")

# if __name__ == '__main__':
# unittest.main(argv=['first-arg-is-ignored'], exit=False)

When any_order=True, all calls in your list must be present in the mock's call history, but their relative order doesn't matter.

Inspecting Mock Calls (mock_calls, call_args_list)

Sometimes it's helpful to see what calls were actually made to the mock for debugging purposes.

  • mock.call_args_list: A list containing the arguments for each call made directly to the mock object itself. Each item in the list is a call object.
  • mock.mock_calls: A more comprehensive list including calls made to the mock and calls made to any of its methods or attributes that are also mocks.
from unittest.mock import Mock, call

mock_object = Mock()
mock_object.some_method = Mock() # Attribute is also a mock

# Calls
mock_object(1, 2)
mock_object.some_method('a', 'b')
mock_object(key='value')

# Inspect call_args_list (only direct calls to mock_object)
print(f"mock.call_args_list:")
print(mock_object.call_args_list) # Output: [call(1, 2), call(key='value')]

# Inspect mock_calls (includes calls to mock_object AND mock_object.some_method)
print(f"\nmock.mock_calls:")
print(mock_object.mock_calls) # Output: [call(1, 2), call.some_method('a', 'b'), call(key='value')]

Choosing the Right Assertion Method

  • Use assert_called_with() when you only care about the arguments of the very last call.
  • Use assert_called_once_with() when you need to ensure the mock was called exactly one time with specific arguments.
  • Use assert_any_call() when you need to confirm a call with specific arguments happened at some point, regardless of other calls.
  • Use assert_has_calls() when you need to verify a specific sequence of calls (use any_order=True if the order doesn't matter but all calls must be present).

Conclusion

Verifying mock interactions is essential for effective testing with unittest.mock. Python provides specific assertion methods to check how your mocks were called:

  • assert_called_with: Checks the last call's arguments.
  • assert_called_once_with: Checks a single call with specific arguments.
  • assert_any_call: Checks if a call with specific arguments ever occurred.
  • assert_has_calls: Checks for a sequence of calls (ordered or unordered).

Choose the assertion method that most accurately reflects the specific interaction you need to verify in your test. Use mock.call_args_list and mock.mock_calls to inspect the actual calls during debugging.