Зачем нужно внедрение зависимостей? Оно уменьшает связанность компонентов в приложение и упрощает тестирование. У некоторых разработчиков есть мнение, что внедрение зависимостей нужно только в больших проектах и что оно сильно усложняет программы. Думаю, это исторически сложилось из-за популярный фрейморков вроде Спринга или Джуса в Джаве. Особенно из-за Спринга, который является невероятным комбайном.
Python-inject — это небольшая библиотека для внедрения зависимостей в Питоне. Третья версия написана в unix-стиле, т.е. она прекрасно выполняет только одну фукнцию и не пытается быть всем. В отличие от уже упомянутых Спринга и Джуса Инжект не ворует конструкторы классов у разработчиков, не навязывает разработчикам необходимость писать приложение в каком-то определенном стиле и не пытается управлять всем графом объектов приложения.
Инжект практически не требует конфигурации (об этом подробнее подкатом) и очень прост в использовании.
# Возможные зависимости
class Db(object): pass
class Mailer(object): pass
# Внедряем зависимости в класс пользователя
class User(object):
db = inject.attr(Db)
mailer = inject.attr(Mailer)
def __init__(self, name):
self.name = name
def register(self):
self.db.save(self)
self.mailer.send_welcome_email(self.name)
# Используем в тестах inmemory базу данных и моки.
class TestUser(unittest.TestCase):
def setUp(self):
inject.clear_and_configure(lambda binder: binder
.bind(Db, InMemoryDb())
.bind(Mailer, Mock()))
self.mailer = inject.instance(Mailer)
def test_register__should_send_welcome_email(self):
# Пример теста.
user = User('John Doe')
# Регистрируем нового пользователя.
user.register()
# Должно отправиться письмо с приветствием.
self.mailer.send_welcome_email.assert_called_with('John Doe')