Как использовать `mock.call()` для проверки последовательности вызовов в мок-объектах?

Для проверки последовательности вызовов мок-объекта с использованием mock.call(), можно использовать методы mock_object.mock_calls и сравнить их с ожидаемой последовательностью вызовов, представленной списком объектов mock.call(). Пример:

import unittest
from unittest import mock

def my_function(obj):
    obj.method_one(1, 2)
    obj.method_two('a')
    obj.method_one(3)

class MyTest(unittest.TestCase):
    def test_call_sequence(self):
        mock_obj = mock.Mock()
        my_function(mock_obj)

        expected_calls = [
            mock.call.method_one(1, 2),
            mock.call.method_two('a'),
            mock.call.method_one(3)
        ]
        self.assertEqual(mock_obj.mock_calls, expected_calls)
  
В данном примере проверяется, что mock_obj вызывался именно в той последовательности и с теми аргументами, которые определены в expected_calls. mock_obj.mock_calls возвращает список всех вызовов мок-объекта, которые можно сравнить с ожидаемым списком.

Для проверки последовательности вызовов в мок-объектах с помощью mock.call(), необходимо создать список ожидаемых вызовов с использованием mock.call() для каждого вызова и затем сравнить этот список с атрибутом mock_object.mock_calls.

Пример:


import unittest
from unittest import mock

class TestMyClass(unittest.TestCase):

    def test_sequence_of_calls(self):
        # Создаем мок-объект
        my_mock = mock.Mock()

        # Выполняем несколько вызовов мок-объекта в определенной последовательности
        my_mock.method_one(1, 'a')
        my_mock.method_two(param1='b')
        my_mock.method_one(2, 'c')


        # Создаем список ожидаемых вызовов, используя mock.call()
        expected_calls = [
            mock.call.method_one(1, 'a'),
            mock.call.method_two(param1='b'),
            mock.call.method_one(2, 'c'),
        ]

        # Проверяем, соответствует ли последовательность вызовов ожидаемой
        self.assertEqual(my_mock.mock_calls, expected_calls)

if __name__ == '__main__':
    unittest.main()
  

Разъяснение:

  • mock.call.method_one(1, 'a') создает объект call, представляющий вызов метода method_one с аргументами 1 и 'a'.
  • Атрибут my_mock.mock_calls является списком, содержащим все вызовы, которые были сделаны к мок-объекту, в порядке их выполнения.
  • Функция self.assertEqual(my_mock.mock_calls, expected_calls) сравнивает список фактически выполненных вызовов (my_mock.mock_calls) со списком ожидаемых вызовов (expected_calls). Если они совпадают, тест проходит; в противном случае - тест падает.

Дополнительные моменты:

  • Порядок элементов в списке expected_calls имеет значение. Последовательность вызовов должна строго соответствовать ожидаемой.
  • mock.call может использоваться с позиционными и именованными аргументами.
  • Этот метод эффективен для проверки, что методы мок-объекта были вызваны именно в том порядке и с теми аргументами, которые ожидаются.
  • При использовании mock.ANY в mock.call, можно игнорировать конкретные значения аргументов и проверять только факт вызова метода. Пример: mock.call.method_one(mock.ANY, 'a') проверит, что был вызван `method_one` с любым первым аргументом и вторым аргументом `'a'`.
0