Как можно использовать контейнер IoC для модульного тестирования? Полезно ли управлять макетами в огромном решении (более 50 проектов) с помощью IoC? Есть опыт? Любые библиотеки C #, которые хорошо подходят для использования в модульных тестах?
Как можно использовать контейнер IoC для модульного тестирования? Полезно ли управлять макетами в огромном решении (более 50 проектов) с помощью IoC? Есть опыт? Любые библиотеки C #, которые хорошо подходят для использования в модульных тестах?
Ответы:
Вообще говоря, контейнер DI не должен быть необходим для модульного тестирования, потому что модульное тестирование - это разделение ответственности.
Рассмотрим класс, который использует внедрение конструктора
public MyClass(IMyDependency dep) { }
Во всем вашем приложении может быть скрытый огромный граф зависимостей IMyDependency
, но в модульном тесте вы сводите все это до одного Test Double .
Вы можете использовать динамические макеты, такие как Moq или RhinoMocks, для создания Test Double, но это не обязательно.
var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);
В некоторых случаях может быть неплохо иметь контейнер с автоматическим макетом , но вам не нужно использовать тот же контейнер DI, который использует производственное приложение.
Как можно использовать контейнер Ioc для модульного тестирования?
IoC будет применять парадигмы программирования, которые упростят изолированное модульное тестирование (то есть с использованием моков): использование интерфейсов, без new (), без синглтонов ...
Но использование контейнера IoC для тестирования на самом деле не является требованием, он просто предоставит некоторые возможности, например, внедрение имитаций, но вы можете сделать это вручную.
Полезно ли управлять mock-объектами в огромном решении (50+ проектов) с помощью IoC?
Я не совсем понимаю, что вы имеете в виду, говоря об управлении макетами с помощью IoC. Во всяком случае, контейнеры IoC обычно могут делать больше, чем просто вводить макеты, когда дело доходит до тестирования. И если у вас есть достойная поддержка IDE, которая делает возможным рефакторинг, почему бы не использовать ее?
Есть опыт?
Да, для огромного решения вам больше, чем когда-либо, нужно решение, не подверженное ошибкам и нежелательное для рефакторинга (т.е. либо через типобезопасный контейнер IoC, либо через хорошую поддержку IDE).
Я часто использую в своих тестах контейнер IoC. Конечно, они не являются «юнит-тестами» в чистом смысле. IMO Они больше 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/
Используя контейнеры с возможностью разрешать незарегистрированные / неизвестные службы, такие как SimpleInjector , DryIoc (его моя шахта) может возвращать фиктивные сообщения для еще не реализованных интерфейсов.
Это означает, что вы можете начать разработку с первой простой реализации и ее фиктивных зависимостей и по мере продвижения заменять их реальными вещами.