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.
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.
In my opinion, the real purpose of testing or specifically TDD is to have better designed code. If writing tests for your code is becoming difficult, then it signifies that your code is highly coupled and you need to refactor it. Besides, writing tests that assert the order of the functions, make tests too coupled to the code and highly fragile.
With that said, you can test the order, in a little hackish way though. Say, you have two functions named func_a
and func_b
, and you want to ensure func_a
is called before func_b
. Replace func_a
with a mock that returns some random value such that it stops execution from happening any further. Mock func_b
as well, and ensure func_a
is called and func_b
is not called. You need to do this for other permutations as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With