Передавайте реализацию SendMessage в сервис через конструктор, а не создавайте SendMail внутри бизнес-метода. Тогда отправитель заменяется без изменения сценария, в том числе тестовым объектом.
Создание сервиса отправки email с применением Dependency Injection
Передавайте реализацию SendMessage в сервис через конструктор, а не создавайте SendMail внутри бизнес-метода. Тогда отправитель заменяется без изменения сценария, в том числе тестовым объектом.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо реализовать механизм отправки электронных писем, строго следуя принципу внедрения зависимостей. Определите абстрактный базовый класс SendMessage и его конкретную реализацию SendMail.
from abc import ABC, abstractmethod
class SendMessage(ABC):
@abstractmethod
def send(self, res: str, text: str, subject: str) -> None:
pass
class SendMail(SendMessage):
def send(self, res: str, text: str, subject: str) -> None:
print("Email:", res, text, subject)
Ответ
Передавайте реализацию SendMessage в сервис через конструктор, а не создавайте SendMail внутри бизнес-метода. Тогда отправитель заменяется без изменения сценария, в том числе тестовым объектом.
К существующим интерфейсу и адаптеру добавьте потребителя:
class NotificationService:
def __init__(self, sender: SendMessage):
self.sender = sender
def notify(self, recipient: str, text: str, subject: str) -> None:
self.sender.send(recipient, text, subject)
service = NotificationService(SendMail())
Связывание выполняется в точке сборки приложения. Для теста передайте fake, записывающий вызовы, без SMTP. Показанный SendMail только печатает данные и не отправляет настоящий email. Рабочий адаптер должен иметь явную обработку ошибок и не выводить содержимое писем/адреса в обычные логи.