Какие основные методы используются для проверки вызовов Mock-объектов в unittest.mock?

«Какие основные методы используются для проверки вызовов Mock-объектов в unittest.mock?» — вопрос из категории Тестирование, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В библиотеке unittest.mock объекты Mock и MagicMock записывают все обращения к ним. Для проверки этих обращений используются специальные методы-утверждения (assertions).

Настройка поведения мока

Перед проверкой вызовов мок обычно настраивают:

  • mock.return_value: Атрибут, который определяет значение, возвращаемое при вызове мока.
  • mock.side_effect: Позволяет задать более сложное поведение: выбросить исключение, вернуть разные значения при последовательных вызовах или выполнить функцию.

Проверка вызовов (Assertions)

Основные методы для проверки взаимодействия с моком:

  • mock.assert_called(): Проверяет, что мок был вызван хотя бы один раз.
  • mock.assert_called_once(): Проверяет, что мок был вызван ровно один раз.
  • mock.assert_not_called(): Проверяет, что мок не вызывался ни разу.
  • mock.assert_called_with(*args, **kwargs): Проверяет, что последний вызов мока был с указанными аргументами.
  • mock.assert_called_once_with(*args, **kwargs): Объединяет assert_called_once() и assert_called_with().
  • mock.assert_any_call(*args, **kwargs): Проверяет, был ли хотя бы один вызов с указанными аргументами среди всех вызовов.
  • mock.call_count: Целочисленный атрибут, содержащий количество вызовов мока.

Практический пример:

Предположим, мы тестируем функцию, которая использует внешний API для отправки уведомлений.

# Код, который мы тестируем
def send_notification(api_client, user_id, message):
    if len(message) > 0:
        api_client.send(user_id, text=message)

# Тест для этого кода
from unittest.mock import Mock
import unittest

class TestNotification(unittest.TestCase):
    def test_send_notification_with_message(self):
        # 1. Arrange: Создаем мок для API клиента
        mock_api = Mock()

        # 2. Act: Вызываем нашу функцию с моком
        send_notification(mock_api, 123, "Hello!")

        # 3. Assert: Проверяем, что метод .send() был вызван один раз
        # и с правильными аргументами.
        mock_api.send.assert_called_once_with(123, text="Hello!")

    def test_send_notification_with_empty_message(self):
        # 1. Arrange
        mock_api = Mock()

        # 2. Act
        send_notification(mock_api, 123, "")

        # 3. Assert: Проверяем, что метод .send() не вызывался
        mock_api.send.assert_not_called()

if __name__ == '__main__':
    unittest.main(argv=['first-arg-is-ignored'], exit=False)