Страницы

Поиск по вопросам

пятница, 26 апреля 2019 г.

Тестирование и избавление от связности классов.

Добрый день! У меня есть приложение asp.net mvc. В нем я пытаюсь создавать архитектуру "по уму" - с Dependency Injection, тестами и тд. В приложении есть классы-сервис, в которых сосредоточена бизнес-логика. Мне необходимо покрыть эти сервисы тестами. Многие сервисы используют класс настроек, экземпляры которых им передаются в конструкторах. Например:
public class AppSettings { public AppSettings() { SomeStr = WebConfigurationManager.AppSettings["str"]).ToString(); // и еще несколько подобных строк }
public string SomeStr { get;set; } }
public class MyService { public MyService(AppSettings settings) { _settings = settings; }
private readonly AppSettings _settings; }
Проблема тут вот какая. В конструкторе класса AppSettings происходит инициализация неких переменных, данные о которых получаются из файла web.config. В коде самого приложения это работает, а вот если я пытаюсь тестировать класс MyService в отдельном тестовом приложении, то возникает проблема: классу нужно передавать экземпляр AppSettings, но при его создании вываливается исключение из-за невозможности обратиться к web.config. Кроме того сами классы я напрямую не создаю, этим занимается DI-библиотека. Как быть в данном случае и как нормально протестировать MyService? К тому же мне кажется проблемой то, что в конструкторе класса AppSettings происходит обращение к `web.config. Подскажите пожалуйста как решить эту проблему? Заранее благодарю.


Ответ

Если вы используете класс AppSettings как класс настроек и IoC-контейнер, то опишите интерфейс IAppSettings и протестируйте с помощью Mock объектов.
Приведу пример. В классе MyService вы заменяете тип аргумента конструктора settings на IAppSetting. В IoC-контейнере регистрируете реализацию. Предположим, что вы используете Ninject, тогда kernel.Bind().To(). Тогда в методе тестирования вы можете настроить свой объект.
Mock() mock = new Mock(); mock.Setup(m => m.Field1).Returns(value1); MyService service = new MyService(mock.Object);
Здесь вы задаете, что при запрашивании Field1 должно вернуться значение value1.
Внимание поле Field1 должно быть определено в интерфейсе IAppSetting

Пример показан для Ninject

Комментариев нет:

Отправить комментарий