Использование IoC для модульного тестирования
Как использовать контейнер IoC для модульного тестирования? Полезно ли управлять макетами в огромном решении (более 50 проектов) с помощью IoC? Есть опыт? Любые библиотеки C#, которые хорошо подходят для использования в модульных тестах?
4 ответа
Вообще говоря, DI-контейнер не должен быть необходим для модульного тестирования, потому что модульное тестирование - это разделение обязанностей.
Рассмотрим класс, который использует конструктор Injection
public MyClass(IMyDependency dep) { }
Во всем приложении может быть огромный граф зависимостей, скрытый за IMyDependency
, но в модульном тесте вы сводите все до одного Test Double.
Вы можете использовать динамические макеты, такие как Moq или RhinoMocks, чтобы генерировать Test Double, но это не обязательно.
var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);
В некоторых случаях может быть полезно иметь автоматически смоделированный контейнер, но вам не нужно использовать тот же DI-контейнер, который использует производственное приложение.
Я часто использую контейнер I oC в своих тестах. Конечно, они не являются "модульными тестами" в чистом смысле. ИМО Они больше BDDish и облегчают рефакторинг. Есть тесты, чтобы придать вам уверенность в рефакторинге. Плохо написанные тесты могут быть похожи на заливку цемента в ваш код.
Учтите следующее:
[TestFixture]
public class ImageGalleryFixture : ContainerWiredFixture
{
[Test]
public void Should_save_image()
{
container.ConfigureMockFor<IFileRepository>()
.Setup(r => r.Create(It.IsAny<IFile>()))
.Verifiable();
AddToGallery(new RequestWithRealFile());
container.VerifyMockFor<IFileRepository>();
}
private void AddToGallery(AddBusinessImage request)
{
container.Resolve<BusinessPublisher>().Consume(request);
}
}
При добавлении изображения в галерею происходит несколько вещей. Размер изображения изменяется, создается миниатюра, а файлы сохраняются на AmazonS3. Используя контейнер, я могу легче изолировать только то поведение, которое хочу протестировать, что в данном случае является постоянной частью.
При использовании этой методики удобно использовать расширение контейнера с автоматической фиксацией: http://www.agileatwork.com/auto-mocking-unity-container-extension/
Как использовать контейнер Ioc для модульного тестирования?
IoC обеспечит применение программных парадигм, которые упростят модульное тестирование (то есть использование имитаций): использование интерфейсов, без new(), без синглетонов...
Но использование контейнера IoC для тестирования на самом деле не является обязательным требованием, оно просто предоставляет некоторые возможности, например, инъекцию макетов, но вы можете сделать это вручную.
Полезно ли управлять макетами в огромном решении (более 50 проектов) с помощью IoC?
Я не уверен, что вы имеете в виду под управлением макетами с помощью IoC. В любом случае, когда речь заходит о тестировании, контейнеры IoC могут делать больше, чем просто вводить макеты. И если у вас есть приличная поддержка IDE, которая делает возможным рефакторинг, почему бы не использовать его?
Есть опыт?
Да, для огромного решения вам необходимо более чем когда-либо не подверженное ошибкам и не допускающее рефакторинга решение (т. Е. Либо через безопасный для типов контейнер IoC, либо с хорошей поддержкой IDE).
Используя контейнеры с возможностью разрешения незарегистрированных / неизвестных сервисов, таких как SimpleInjector, DryIoc (его мой) может возвращать макеты для еще не реализованных интерфейсов.
Это означает, что вы можете начать разработку с первой простой реализации и ее поддельных зависимостей и заменить их реальными вещами по мере продвижения.