Ответ
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]).
Ответ 18+ 🔞
Слушай, вот сидишь ты, пишешь тесты, и тут на тебе — надо какой-то объект подменить, чтобы он не лез в базу, не слал письма и вообще не устраивал цирк. Ну, в общем, заглушку сделать. И тут тебе на выбор: Mock или MagicMock. Как будто в магазине — колбаса варёная или копчёная. А разница-то, блядь, есть!
Mock — это как простой солдат, тупой и прямолинейный.
Можешь ему сказать: «Вот, Вася, у тебя будет метод calculate(), и он должен возвращать 42». И Вася, ёпта, так и сделает. Но если ты попробуешь с ним какую-нибудь магию провернуть — типа len(вася) или for item in вася — он тебе сразу в глаза посмотрит и скажет: «Ты чё, мудак? Я такого не умею». И кинет TypeError. Честно, без подвохов.
from unittest.mock import Mock
объект = Mock()
объект.посчитать.return_value = 42
print(объект.посчитать()) # Выведет 42, всё чётко
# А теперь попробуй с ним магию...
try:
len(объект)
except TypeError as e:
print(e) # Выведет: object of type 'Mock' has no len()
# Ну вот, обосрался, блядь. Так и знал.
MagicMock — это тот же солдат, но с курсом молодого волшебника.
Он всё то же самое умеет, но ещё и магические методы у него из коробки работают. Хочешь, чтобы он вёл себя как список? Без проблем! Хочешь, чтобы его можно было сложить с чем-то? Да хуй с ним, сделаем вид! Он же магический, ёпта.
from unittest.mock import MagicMock
волшебный_объект = MagicMock()
# Сделаем вид, что его длина — 100500
волшебный_объект.__len__.return_value = 100500
print(len(волшебный_объект)) # Выведет 100500, вот это да!
# А теперь представим, что он итерируемый
волшебный_объект.__iter__.return_value = iter(['а', 'б', 'в'])
for буква in волшебный_объект:
print(буква) # Выведет а, б, в — красота, блядь!
Так когда что брать, а?
-
Берёшь
Mock, когда тебе нужна простая заглушка, и ты точно знаешь, что магические методы тебе не понадобятся. Это как взять голый каркас — ничего лишнего, зато тест строгий и явный. Если код вдруг попытается вызвать__str__— получит по ебалу, и ты сразу узнаешь, что что-то пошло не так. -
Берёшь
MagicMock, когда тестируемый код общается с твоим объектом через эти самые магические методы. Например, если там естьlen(obj),obj[key],for x in objили ещё какая-нибудь хуйня.MagicMockуже всё это умеет «из коробки», поэтому не придётся каждый раз вручную настраивать__len__или__getitem__.
Короче, если сомневаешься — бери MagicMock. Он покроет большинство сценариев, и не придётся потом, блядь, дописывать магию руками. Но если хочешь быть уверен, что тест упадёт при любой попытке наебнуть систему — Mock твой друг. Выбор за тобой, пидор шерстяной!