В чем разница между Mock и MagicMock в библиотеке unittest.mock Python

Ответ

Mock и MagicMock — это классы из стандартной библиотеки Python unittest.mock, предназначенные для создания объектов-заглушек (моков) в тестах. MagicMock является подклассом Mock с расширенной функциональностью.

Mock (базовый класс)

Позволяет имитировать любые атрибуты и методы, но не поддерживает по умолчанию "магические" (dunder) методы, такие как __len__, __str__, __iter__, и операторы (+, ==). При попытке их использования будет вызвано исключение TypeError.

Пример:

from unittest.mock import Mock

my_mock = Mock()
my_mock.some_method.return_value = 'Success'

print(my_mock.some_method()) # Выведет: Success

try:
    len(my_mock)
except TypeError as e:
    print(e) # Выведет: object of type 'Mock' has no len()

MagicMock (расширенный класс)

Наследует все возможности Mock, но дополнительно поддерживает большинство магических методов "из коробки". Им уже задано поведение по умолчанию, которое можно переопределить. Это делает его идеальным для имитации объектов, которые ведут себя как контейнеры, числа или другие встроенные типы.

Пример:

from unittest.mock import MagicMock

magic_mock = MagicMock()

# Переопределяем поведение __len__
magic_mock.__len__.return_value = 42
print(len(magic_mock)) # Выведет: 42

# MagicMock можно использовать как итерируемый объект
magic_mock.__iter__.return_value = iter(['a', 'b'])
for item in magic_mock:
    print(item)

Когда что выбрать?

  • Mock: Используйте, когда вам нужна простая заглушка для объекта и не требуется эмуляция магических методов. Это делает тест более строгим и явным.
  • MagicMock: Используйте, когда тестируемый код взаимодействует с вашим объектом через магические методы (например, len(obj), for item in obj, obj[key]).