Ответ
Dependency Injection (DI) кардинально улучшает тестируемость кода, так как позволяет подменять реальные зависимости тестовыми двойниками (моками, стабами).
Основная идея в том, что компонент не создаёт свои зависимости сам, а получает их извне. Это разрывает жёсткие связи между классами.
Преимущества для тестирования:
- Изоляция: Можно тестировать один класс изолированно от его зависимостей.
- Скорость: Тесты выполняются быстрее, так как не требуют подключения к реальным базам данных или отправки сетевых запросов.
- Предсказуемость: Поведение моков полностью контролируется в тесте, что делает результаты стабильными.
Пример
Код без DI (сложно тестировать):
class PaymentGateway:
def charge(self, amount: float):
# Сложная логика с реальным API
print(f"Charging {amount} via external API...")
class OrderProcessor:
def process(self, order):
# Зависимость создаётся внутри класса - это проблема
payment_gateway = PaymentGateway()
payment_gateway.charge(order.total)
Код с DI (легко тестировать):
class OrderProcessor:
# Зависимость передаётся в конструктор
def __init__(self, payment_gateway):
self.payment_gateway = payment_gateway
def process(self, order):
self.payment_gateway.charge(order.total)
Пример теста с использованием мока:
from unittest.mock import Mock
def test_order_processor_charges_correct_amount():
# 1. Создаём мок-объект для зависимости
mock_gateway = Mock()
# 2. Внедряем мок в тестируемый класс
processor = OrderProcessor(payment_gateway=mock_gateway)
order = Mock(total=150.0)
# 3. Выполняем действие
processor.process(order)
# 4. Проверяем, что метод мока был вызван с правильными данными
mock_gateway.charge.assert_called_with(150.0)