У меня есть три функции, порядок вызова которых я пытаюсь проверить.
Скажем, в модуле module.py у меня есть следующее
# module.py
def a(*args):
# do the first thing
def b(*args):
# do a second thing
def c(*args):
# do a third thing
def main_routine():
a_args = ('a')
b_args = ('b')
c_args = ('c')
a(*a_args)
b(*b_args)
c(*c_args)
Я хочу проверить, что b вызывается после a и до c. Так что получить макет для каждого из a, b и c легко:
# tests.py
@mock.patch('module.a')
@mock.patch('module.b')
@mock.patch('module.c')
def test_main_routine(c_mock, b_mock, a_mock):
# test all the things here
Проверить, что каждый из отдельных имитаций вызван, тоже несложно. Как мне проверить порядок вызовов относительно друг друга?
call_args_list
не будет работать, так как поддерживается отдельно для каждого макета.
Я пробовал использовать побочный эффект для регистрации каждого из вызовов:
calls = []
def register_call(*args):
calls.append(mock.call(*args))
return mock.DEFAULT
a_mock.side_effect = register_call
b_mock.side_effect = register_call
c_mock.side_effect = register_call
Но это дает мне только аргументы, с которыми были вызваны макеты, но не фактический макет, против которого был сделан вызов. Могу добавить немного логики:
# tests.py
from functools import partial
def register_call(*args, **kwargs):
calls.append(kwargs.pop('caller', None), mock.call(*args, **kwargs))
return mock.DEFAULT
a_mock.side_effect = partial(register_call, caller='a')
b_mock.side_effect = partial(register_call, caller='b')
c_mock.side_effect = partial(register_call, caller='c')
И это, кажется, делает работу ... Но есть ли способ лучше? Похоже, что в API уже должно быть что-то, что может сделать это, что мне не хватает.