2017-01-30 6 views
8

Я предпочитаю, чтобы мои обработчики не обладали инфраструктурой ASP.NET, которую очень сложно проверить (да, даже в ASP.NET Core). Но иногда это происходит, и у вас есть зависимость, такая как UserManager (я хотел бы узнать, почему однажды это не интерфейс), HttpContext и т. Д., А модульные тесты превращаются в насмешливый ад.ASP.NET-инфраструктура в обработчиках MediatR

Я попытался использовать тестирование интеграции, чтобы справиться с этим, создав TestServer и получив всю инфраструктуру ASP.NET для каждого вызова api. Он работает довольно хорошо, но иногда кажется излишним, если я хочу проверить простую логику моего обработчика. И хотя он решает техническую проблему издевательской инфраструктуры ASP.NET, он сохраняет архитектурную проблему (если вы так считаете) о наличии инфраструктуры ASP.NET в своих обработчиках.

Хотелось бы узнать, какие рекомендуемые подходы к его решению?

+0

Если вас интересует абстрагирование UserManager и Identity, взгляните на ответ, который я привел здесь: http://stackoverflow.com/a/38464229/5233410 – Nkosi

+0

Я нашел [это] (https://lostechies.com/) jimmybogard/2016/10/24/vertical-slice-test-fixtures-for-mediatr-and-asp-net-core /) и [this] (https://lostechies.com/patricklioi/2016/01/27/ мощная интеграция-тестирование /), чтобы быть очень полезной в том, чтобы держать обработчиков чистыми и легко проверяемыми. Сообщения от Джимми Богарда и Патрика Лиои соответственно. – trevorc

+0

@trevorc, это отличные подходы. Не могли бы вы ответить и ответить о своем опыте? – SiberianGuy

ответ

1

Я бы сказал, это зависит от уровня уверенности, который вы хотите получить в конце. Если вы хотите убедиться, что вся система работает так, как ожидалось, то интеграционные тесты с использованием TestServer, вероятно, являются способом выхода.

Одно из преимуществ MediatR заключается в том, что это позволяет отделить вашу бизнес-логику от приложения, использующего его, поэтому на самом верхнем уровне, допустим, в контроллерах нет логики, а просто делегирование посреднику ,

При этом вы правы, что иногда вашей логике нужна информация из приложения-хостинга. Примером может служить пользователь, делающий запрос, доступный в контексте HTTP.

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

Это имеет смысл?

+0

Да, это так. Спасибо! Я также рассмотрел возможность использования предварительной обработки Mediatr для «обогащения» команд/запросов с помощью специфичных для каркаса элементов (то есть, если мне нужно получить какой-то URL-адрес, мне не нужно вводить IUrlHelper), но этот подход кажется громоздким. – SiberianGuy

+0

Я не уверен, что понимаю. Не могли бы вы подробнее рассказать? –

1

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

Для тех классов, которые являются статическими, например, для чтения настроек web.config, одна из стратегий, которые мне нравятся, заключается в том, что вокруг них создается связанный с ними класс оболочки. В то время как ConfigurationManager статичен, я все еще могу просто написать обычный класс с интерфейсом, в который я помещал методы или свойства для чтения определенного параметра (предпочтительно семантически названного) из Configuration Manager. Теперь я могу легко высмеять любой сконфигурированный параметр (или его отсутствие) в своем тесте, просто издеваясь над интерфейсом и настраивая разные возвращаемые значения.

3

Я чувствую вашу боль. Я наткнулся на фантастический blob post от Джимми Богарда, который справляется с этой проблемой, используя то, что Мартин Фаулер называет Subcutaneous Tests. Я оставлю глубокое объяснение этим экспертам, но в двух словах подкожные тесты просто избегают всех трудных для тестирования аспектов пользовательского интерфейса.

Бесстыдный плагин: В настоящее время я записываю wiki, который демонстрирует эти шаблоны в образце сквозного проекта на github. Это непросто следовать, но, вероятно, слишком много кода для сообщения для ответа SO.

Суммировать:

  • Если вы используете MediatR правильно контроллеры должны быть очень тонкими, что делает их тестирование бессмысленно.
  • Что вы хотите проверить, это ваши обработчики.
  • Однако вы хотите протестировать свои обработчики как часть вашего реального мира.

Чтобы решить:

  1. Wrap запрос HTTP-в сделке.
  2. Постройте тестовое крепление, которое имитирует приложения. Startup.cs
  3. Установка тестового сервера db для выполнения команд запросов против, но также сбрасывается после каждого теста.

Это в основном это. Каждый раз, когда вы запускаете интеграционный тест с одним из ваших обработчиков:

  • Окружающая среда для хостинга издевается, но ваше приложение запускается в реальном мире.
  • Ваш запрос или команда завернуты в транзакцию, имитирующую ваш DbContext.
  • Обработчик выполняется против реальной базы данных и затем сбрасывается.

Я бы добавил еще несколько примеров кода к моему ответу, но между сообщением в блоге и предоставленной мной wiki гораздо проще следовать примерам кода.