Search code examples
pythonunit-testingassert

How to unittest the sequence of function calls made inside a python fuction?


I would like to unittest a fuction and assert if the sequence of function calls made inside the function workflow(). Something like,

      [1st called] fetch_yeargroup_ls()
      [2nd called] invoke_get_links()....... 

I searched across many discussions but never found one answering my question.


Solution

  • If you are using mock you can create mocks as attributes of a parent mock, when patching out those functions:

    try:
        # Python 3
        from unittest.mock import MagicMock, patch, call
    except ImportError:
        # Python 2, install from PyPI first
        from mock import MagicMock, patch, call
    import unittest
    
    from module_under_test import function_under_test
    
    class TestCallOrder(unittest.TestCase):
        def test_call_order(self):
            source_mock = MagicMock()
            with patch('module_under_test.function1', source_mock.function1), \
                    patch('module_under_test.function2', source_mock.function2), \
                    patch('module_under_test.function3', source_mock.function3)
    
                # the test is successful if the 3 functions are called in this
                # specific order with these specific arguments:
                expected = [
                    call.function1('foo'),
                    call.function2('bar'),
                    call.function3('baz')
                ]
    
                # run your code-under-test
                function_under_test()
    
                self.assertEqual(source_mock.mock_calls, expected)
    

    Because the 3 functions are attached to source_mock, all calls to them are recorded on the parent mock object in the Mock.mock_calls attribute and you can make assertions about their call order.

    I attached the 3 function mocks simply by looking them up as attributes on the source_mock object, but you could also use the Mock.attach_mock() method to attach mocks you created in a different way to a parent.