Как заставить DbContext при использовании оператора работать с модульными тестами? - PullRequest
0 голосов
/ 01 июня 2018

У меня такая ситуация:

  1. Я работаю над проектом ASP.NET MVC, который не реализует шаблон хранилища
  2. Все вызовы DbContext выполняются изуровень контроллера
  3. DbContext заключен в оператор using и создается по мере необходимости для целей управления памятью, а не для целей пула соединений
  4. Нам необходимо выполнить модульное тестирование этих контроллеров, что означает внедрение DbContext в контроллер.
  5. Мы не используем контейнер IoC.Мне пришлось бы создать новый экземпляр в конструкторе без параметров и использовать его в течение всего жизненного цикла действия контроллера.
  6. Я не могу изменить большинство этих условий.

Условия, которые я могу изменить:

  1. Избавьтесь от оператора using, если надежный вариант может занять его место.
  2. Примите этот код простоне проверяемый как есть и переходящий к расходу энергии в другом месте.

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

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

Есть мысли по этому поводу?

Ответы [ 2 ]

0 голосов
/ 02 июня 2018

Создание DbContext внутри метода, который вы хотите протестировать, ничем не отличается от создания любого другого конкретного экземпляра зависимости в коде, это означает, что вы не можете тестировать с помощью симулированной зависимости.Поэтому на ум приходят следующие варианты (без изменений кода / структуры):

  • Реализация провайдера данных в памяти, чтобы указать EF для модульных тестов.
  • Настройкабаза данных с известным состоянием, которую можно восстановить между тестовыми прогонами.(Это скорее интеграционный тест, не очень подходящий для TDD, где вам нужны тесты, которые могут выполняться очень быстро, очень часто.)
  • Поместите его в корзину "не предназначено для модульного тестирования" из-за отсутствияDI / IoC

Насмешка над DbContext - это грязно, но выполнимо.После того, как у вас будет один макет, я бы порекомендовал добавить в проект контейнер IoC, такой как Autofac.Я не знаю обстоятельств, которые помешали бы вам внедрить контейнер IoC, но если команда беспокоится о том, что это ре-фактор «все или ничего» и слишком большая работа, то я бы заверила их, что этомогут быть добавлены с минимальными изменениями в проект и таким образом, чтобы не нарушать существующий код.Помимо DbContext, если код не использует DI / IoC Container, как вы планируете обрабатывать другие конкретные зависимости?Вам не нужно переключать все зависимости / контроллеры за один раз, но улучшать их постепенно.

Как только контейнер настроен для разрешения контроллеров MVC, существующие контроллеры с конструкторами по умолчанию будутне быть затронутым.Затем вы можете зарегистрировать свой DbContext в контейнере и настроить тестируемый контроллер так, чтобы он принимал контекст в конструкторе.Контейнер IoC, например, настроил бы область действия DbContext на Instance per Request, поэтому вам не нужен блок using {}.Оттуда ваши тесты могут предоставить поддельный DbContext, в то время как контейнер управляет временем жизни контекста.

Что касается создания дружественных для модульных тестов контроллеров / кода с контейнером IoC, я недавно опубликовал статью об использовании Lazy зависимостей / w Autofac, чтобы сделать написание тестов для классов с несколькими зависимостями проще простого.Вы можете прочитать на https://medium.com/@StevePy/writing-easily-testable-code-with-autofac-lazy-properties-f9c63457c8ce

0 голосов
/ 01 июня 2018

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

Скорее всего, создайте конструктор, который принимает объект DbContext.В своем модульном тесте создайте свой «поддельный» DbContext и передайте его контроллеру.Контроллер не создает DbContext, если он его получил.

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

Поскольку нет МОК, DI удивителен при разработке TDD.Он встроен в .Net Core, поэтому эти ограничения являются тупиковыми.

...