Ошибки/Исключения Python
И всем тем программистам языка C-выхода, сам имеет больше смысла мне, чем это, потому что объект относится к сам
Я стараюсь как можно меньше использовать ядро DI непосредственно в моем коде, вместо этого полагаясь на внедрение конструктора (или свойства в некоторых случаях, например, Атрибут
классы). Там, где я должен, однако, использовать уровень абстракции, чтобы я мог установить объект ядра DI, делая его подделываемым в модульных тестах.
Например:
public interface IDependencyResolver : IDisposable
{
T GetImplementationOf<T>();
}
public static class DependencyResolver
{
private static IDependencyResolver s_resolver;
public static T GetImplementationOf<T>()
{
return s_resolver.GetImplementationOf<T>();
}
public static void RegisterResolver( IDependencyResolver resolver )
{
s_resolver = resolver;
}
public static void DisposeResolver()
{
s_resolver.Dispose();
}
}
Используя подобный шаблон, вы можете установить ] IDependencyResolver
из модульных тестов путем вызова RegisterResolver
с имитацией или поддельной реализацией, которая возвращает любые объекты, которые вы хотите, без необходимости подключать полные модули. У него также есть вторичное преимущество абстрагирования вашего кода от конкретного контейнера IoC, если вы решите переключиться на другой в будущем.
Естественно, ты » d также хочу добавить дополнительные методы в IDependencyResolver
, как того требуют ваши потребности, я просто включаю здесь основы в качестве примера. Да, тогда для этого потребуется написать супер-простую оболочку вокруг ядра Ninject, которая также реализует IDependencyResolver
.
Причина, по которой вы хотите это сделать, заключается в том, что ваши модульные тесты действительно должны тестировать только один вещь, и используя свой фактический контейнер IoC, вы действительно тренируете больше, чем один тестируемый класс, что может привести к ложноотрицательным результатам, которые сделают ваши тесты хрупкими и (что более важно) со временем поколебят веру разработчиков в их точность. Это может привести к апатии и отказу от тестирования, поскольку становится возможным, что тесты не пройдут, но программное обеспечение по-прежнему будет работать правильно («не волнуйтесь, он всегда терпит неудачу, это»
Что я обычно делаю, так это создаю отдельный тестовый проект с его собственными привязками - я, конечно, предполагаю, что мы говорим о каких-то модульных тестах. Тестовый проект использует собственное ядро и загружает модуль из тестового проекта в это ядро. Тесты в проекте выполняются во время сборок CI и полными сборками, выполняемыми из сценария сборки, хотя тесты никогда не развертываются в производственной среде.
Я понимаю, что ваш проект / решение может не допускать такого рода организацию, но это довольно типично из того, что я видел.
Подход Питера Майера может быть полезен для модульного тестирования, но ИМХО, не проще ли просто вручную ввести Mock с помощью инъекции конструктора / свойства?
Мне кажется, что использование определенных привязок для тестового проекта будет более полезным для другой вид теста (интеграционный, функциональный), но даже в этом случае вам обязательно нужно изменить привязки в зависимости от теста.
Мой подход представляет собой своего рода смесь кронбаха и Хэмиша Смита, создающую «преобразователь зависимостей», где вы можете зарегистрировать и отменить регистрацию используемых модулей.
Я бы добавил в MyClass конструктор, который принимает модуль.
Это не будет использоваться в производстве, но будет использоваться в тестах.
В тестовом коде я бы передал модуль, который определил требуемые тестовые двойники.
Для проекта, над которым я работаю, я создал отдельные модули для каждой среды (тестирование, разработка, этап, производство и т. Д.). Эти модули определяют привязки.
Поскольку dev, stage и production используют одни и те же привязки, я создал общий модуль, из которого они все являются производными. Каждый из них затем добавляет привязки, специфичные для среды.
У меня также есть KernelFactory, который при передаче токена среды будет загружать IKernel с соответствующими модулями.
Это позволяет мне переключать свой токен среды, который, в свою очередь, изменится все мои привязки автоматически.
Но если это для модульного тестирования, я согласен с приведенными выше комментариями, что простой конструктор, позволяющий ручное связывание, - это способ пойти, поскольку он не позволяет Ninject из ваших тестов.