Страницы

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

понедельник, 24 февраля 2020 г.

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

#c_sharp #aspnet #aspnet_mvc #юнит_тесты #тестирование


Добрый день! У меня есть приложение 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. Подскажите
пожалуйста как решить эту проблему? Заранее благодарю.
    


Ответы

Ответ 1



Если вы используете класс 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

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

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