MSTest TestMethod Инъекция зависимостей - PullRequest
6 голосов
/ 24 ноября 2010

Я использую контейнер DI и хочу выполнить модульные тесты MSTest (VS 2010) с экземплярами, разрешенными из контейнера.

Я хотел бы вставить эти экземпляры в мой TestMethod или, по крайней мере,мой TestClass.Возможно ли это?

Прямо сейчас мои TestMethods напрямую вызывают container.Resolve<T>(xxx), чего я бы предпочел избегать, чтобы мои инъекционные испытания были более реалистичными.

У кого-нибудь есть опыт с этим?

Заранее спасибо.

Ответы [ 2 ]

6 голосов
/ 24 ноября 2010

Создание экземпляра тестового класса происходит глубоко во внутренних классах инфраструктуры MSTest, поэтому внедрение зависимостей в него было бы сложной задачей.

5 голосов
/ 24 ноября 2010

Основная причина - для меня - написания кода в соответствии с шаблоном внедрения зависимостей и использования платформ IoC - это получение тестируемого кода.Однако использование контейнера IoC в тестовом коде приведет к противоположному результату.Из вашего вопроса я вижу, что вы уже испытываете это.

Это особенно проблема при использовании шаблона Service Locator (SL) вместо шаблона Dependency Injection (DI).С шаблоном SL класс вызывает IoC-контейнер (или абстракцию такого контейнера) напрямую, вместо того, чтобы предоставлять классу необходимые ему зависимости (используя внедрение конструктора).Поскольку классы вызывают контейнер напрямую, вам необходимо также настроить этот контейнер в тестовой среде.Это болезненно, потому что конфигурация теста или поддельные объекты часто становятся очень сложными, потому что вы часто хотите влиять на поведение подделки для каждого теста, сохраняя при этом потокобезопасность, потому что инфраструктуры тестирования могут запускать ваши тесты параллельно (MSTest делает это).Я знаю, что в прошлом я написал какой-то сумасшедший потокобезопасный тестовый код, прежде чем я обнаружил, что все делал неправильно: - (.

Так что вам следует использовать шаблон DI в коде приложения и втестирует, вы должны подключить эти зависимости вручную. Например, если у вас есть тесты для класса HomeController, который зависит от класса ICustomerService, в вашем тестовом классе обычно должен быть фабричный метод CreateController() или CreateValidController, который централизуетсоздание этого HomeController. Это избавляет вас от записи этих зависимостей в каждом тесте и, таким образом, создает кошмар обслуживания в тестовом коде. В этом заводском методе вы, например, вводите класс FakeCustomerService вручную, выполняя что-то вроде этого:

private static HomeController CreateController(
    InMemoryDataMapper mapper)
{
    var uowFactory = new FakeNorthwindUnitOfWorkFactory()
    {
        UnitOfWork = new NorthwindUnitOfWork(mapper);
    };

    return new HomeController(new FakeCustomerService(uowFactory));
}

Как выглядит такой фабричный метод, конечно, зависит (не каламбур) от того, как выглядит структура зависимостей HomeController.

Короче говоря, не пытайтесьделать внедрение зависимостей в вашем тестовом коде так же, как вы хотите делать в коде приложения.Это затруднит работу rks, это будет означать, что вам придется настроить IoC-фреймворк для вашей тестовой среды, и в этом случае вы столкнетесь с ошибкой.К сожалению, я говорю из опыта.

...