Проверка порядка звонков с помощью pytest-mock
Во фрагменте кода, показанном ниже, я хотел бы проверить порядок вызова функций в run()
функция, т.е. f_3
называется после f_2
что называется после f_1
:
class TestMock:
def f_1(self) -> None:
pass
def f_2(self) -> None:
pass
def f_3(self) -> None:
pass
def run(self) -> None:
self.f_1()
self.f_2()
self.f_3()
Есть ли способ сделать это с помощью pytest-mock
? Я пытался издеваться надf_1
, f_2
, а также f_3
функции в моем тестовом файле и использовать assert_has_calls
с участием any_order=False
Однако безуспешно.
Заранее благодарим за любую помощь или подсказки!
С уважением, Алексей
2 ответа
Вы были на правильном пути с any_order=False
, вам просто нужно знать о attach_mock
характерная черта:
import yourmodule
def test_something(mocker):
mock = mocker.MagicMock()
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_1"), "f_1")
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_2"), "f_2")
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_3"), "f_3")
yourinstance = yourmodule.TestMock()
yourinstance.run()
mock.assert_has_calls(
[
mocker.call.f_1(),
mocker.call.f_2(),
mocker.call.f_3(),
],
any_order=False,
)
Я полностью перешел на unittest.mock
и теперь у вас есть следующий рабочий код:
@mock.patch('.'.join([__name__, 'TestMock', 'f_3']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_2']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_1']))
def test_order_2(f_1: mock.NonCallableMock,
f_2: mock.NonCallableMock,
f_3: mock.NonCallableMock) -> None:
manager = mock.Mock()
manager.attach_mock(f_1, 'f_1')
manager.attach_mock(f_2, 'f_2')
manager.attach_mock(f_3, 'f_3')
obj = TestMock()
obj.run()
manager.assert_has_calls([mock.call.f_1,
mock.call.f_2,
mock.call.f_3], any_order=False)
здесь возникает вопрос: я действительно не понимаю смысла имен атрибутов, поэтому они являются обязательными, но для меня единственные разумные имена - это сами имена функций... Я изменил имена атрибутов следующим образом:
@mock.patch('.'.join([__name__, 'TestMock', 'f_3']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_2']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_1']))
def test_order_1(f_1: mock.NonCallableMock,
f_2: mock.NonCallableMock,
f_3: mock.NonCallableMock) -> None:
manager = mock.Mock()
manager.attach_mock(f_1, f_1._extract_mock_name())
manager.attach_mock(f_2, f_2._extract_mock_name())
manager.attach_mock(f_3, f_3._extract_mock_name())
obj = TestMock()
obj.run()
manager.assert_has_calls([mock.call.f_1,
mock.call.f_2,
mock.call.f_3], any_order=False)
было бы здорово услышать ваше мнение по этому поводу!
кстати, почему f_*
фиктивные объекты относятся к mock.NonCallableMoc
тип? Я ожидал, что они будут заменены фиктивными функциями (Collable
)...
Заранее спасибо за помощь!
С уважением, Алексей