Skip to content

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

Learn how to verify mock interactions in Python using unittest.mock assertions like assert_called_with, assert_called_once_with, assert_any_call, and assert_has_calls to check method calls with exact arguments in unit tests.

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)

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

        mock_object.assert_called_with('arg1', key='val1')
        print("Assertion 1 passed.\n")

        print("Calling: mock_object('arg2')")
        mock_object('arg2')

        mock_object.assert_called_with('arg2')
        print("Assertion 2 passed.\n")

        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}")

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)

        print("Calling: mock_object('first and only', status=True)")
        mock_object('first and only', status=True)

        mock_object.assert_called_once_with('first and only', status=True)
        print("Assertion 1 (single call) passed.\n")

        print("Calling mock_object again...")
        mock_object('second call')

        print("Attempting assert_called_once_with again...")
        with self.assertRaises(AssertionError) as cm:
            mock_object.assert_called_once_with('first and only', status=True)
        print(f"Assertion 2 failed as expected: {cm.exception}")

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')

        mock_object.assert_any_call(name='Alice', age=30)
        print("Assertion 1 (Alice) passed.")

        mock_object.assert_any_call(1, 2)
        print("Assertion 2 (1, 2) passed.")

        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}")

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')

        expected_calls_in_order = [
            call('A'),
            call('B', status='pending'),
            call('C')
        ]

        mock_object.assert_has_calls(expected_calls_in_order)
        print("Assertion 1 (correct order) passed.")

        expected_calls_wrong_order = [
            call('A'),
            call('C'), # Order swapped with B
            call('B', status='pending')
        ]

        print("\nAttempting assert_has_calls with wrong order...")
        with self.assertRaises(AssertionError) as cm:
            mock_object.assert_has_calls(expected_calls_wrong_order)
        print(f"Assertion 2 failed as expected: {cm.exception}")

        partial_sequence = [call('A'), call('B', status='pending')]
        mock_object.assert_has_calls(partial_sequence) # This passes
        print("\nAssertion 3 (partial sequence) passed.")

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')

        expected_calls_any_order = [
            call('C'),
            call('A'),
            call('B', status='pending')
        ]

        mock_object.assert_has_calls(expected_calls_any_order, any_order=True)
        print("Assertion 1 (any_order=True) passed.")

        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}")

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

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

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

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.

Navigation