Как выполнить интеграционное тестирование при миграции EF Core - PullRequest
3 голосов
/ 10 марта 2019

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

С высокого уровня, это то, что я хочу сделать:

  • Организация: в тестовом методе вызовите соответствующие службы для заполнения базы данных.
  • Act: Запустить миграцию, чтобы обновить схему базы данных.
  • Утверждение: целостность данных, т. Е. Начальные данные могут быть доступны согласно обновленной структуре объекта.

Какой смысл в этом?
Ну, это в значительной степени описано в утверждении выше; целостность данных. Миграции в этом проекте выполняются при запуске приложения с использованием Database.Migrate(). Я хотел бы убедиться, что нет никаких потерь / повреждения существующих данных.

Все примеры интеграционного тестирования, с которыми я сталкивался, в основном выполняются Database.Migrate() как часть настройки теста, за которым следует заполнение, а затем утверждение. Это, однако, полезно только при тестировании уровня доступа к данным с использованием схемы latest (со всеми примененными миграциями). Бесполезно проверять влияние конкретной миграции на уже существующие данные.

Вопрос:

Как другие решают проблему проверки целостности данных в процессе миграции? Я ищу установку, которая бы хорошо работала с конвейером CI.

Ответы [ 2 ]

3 голосов
/ 11 марта 2019

Пожалуйста, смотрите мой другой ответ, так как он более новый и намного проще для следующего подхода.

Один вариант, который я могу придумать, будет работать следующим образом ...
(Обратите внимание, что я не проверял это, это просто теория на данном этапе, поэтому не стесняйтесь комментировать, где я мог ошибиться. В конце я сам делал заметки, обращаясь к проблемам, которые я вижу; примечания соответствуют элементам с тегом * или ^)

Предположим, у вас уже есть миграции IM, M1, M2, ..., Mn , где IM - начальная миграция, а миграция Mn - это последняя успешно протестированная миграция. Теперь давайте предположим, что вы хотите протестировать новую миграцию Mn + 1 , которая является результатом (среди прочего) обновления сущности User, чтобы больше не иметь отдельных свойств FirstName и LastName, но вместо этого есть единственное свойство Name. Давайте дадим ему имя MergeFistAndLastNames.

Перед тем как приступить к использованию метода тестирования, вам необходимо точно зафиксировать состояние тестируемой системы (SUT) до применения миграции Mn + 1 . Поэтому сделайте следующее:

  1. Создайте новый тестовый проект для миграции, если он еще не существует.
  2. Удалите из проекта тестирования миграции весь существующий контент ^ (контент описан в следующих шагах).
  3. Поместите в проект теста миграции копию всех сущностей в модели, соответствующих Mn , которые необходимо изменить, чтобы сгенерировать Mn + 1 . Отредактируйте их имена, добавив к ним суффикс (например, Before_MergeFistAndLastNames). Так как сущность User должна быть обновлена, поместите ее копию в тестовый проект и назовите ее User_Before_MergeFirstAndLastNames.
  4. Сделайте то же самое для любых контекстов *, которые необходимо обновить, чтобы сгенерировать Mn + 1 . Итак, предположим (скажем), что MembershipContext необходимо обновить, скопируйте его в тестовом проекте и назовите его MembershipContext_Before_MergeFirstAndLastNames.
  5. Наконец, сделайте то же самое для любых сервисов, которые вам нужно будет вызвать для заполнения тестовой базы данных (если вы используете шаблон Repository, это будут ваши реализации репозитория, которые обычно будут вызываться для изменения базы данных и изменение ваших сущностей может вызвать изменение в ваших реализациях репозитория).


Теперь для вашего метода испытаний ^^ вы будете:

  • Упорядочить: применить все миграции вплоть до Mn , используя IMigrator.Migrate. Затем позвоните в необходимые службы, чтобы заполнить тестовую базу данных **.
  • Act: Используя IMigrator.Migrate снова, примените миграцию Mn + 1 .
  • Утверждение: целостность данных ***.


Примечания:
*: Если контекст копируется в тестовый проект, любые свойства DbSet в нем, которые соответствуют обновленным объектам, необходимо отредактировать вручную, чтобы использовать скопированные объекты. Например, в приведенном выше примере, если MembershipContext_Before_MergeFirstAndLastNames имеет свойство DbSet<User> User {get; set;}, его необходимо изменить на DbSet<User_Before_MergeFirstAndLastNames> User {get; set;}.

**: Вам может понадобиться позвонить в несколько служб. Если вы используете IoC везде, внедрить скопированные сервисы должно быть относительно просто.

***: Утверждение целостности данных действительно зависит от конкретной миграции, которую вы тестируете, и ее потенциальных последствий. Для приведенного выше примера, возможно, стоит проверить, что пользователь, отобранный с использованием (старого способа) отдельного имени и фамилии, все еще может быть получен через обновленный UserService, который должен вернуть User с Name равна объединению имен и фамилий.

^: Тестовый проект миграции должен быть очищен от всего контента при тестировании новой миграции.
Неформальное доказательство. Предположим, это не нужно. Используя приведенный выше пример, этот проект будет содержать метод тестирования со ссылкой на сущность User, соответствующую миграции Mn + 1 . Теперь предположим, что сделано обновление до User, что приводит к более новой миграции Mn + 2 . Существующий метод тестирования может больше не компилироваться, если он ссылается на User таким образом, что больше не применим. ∎

Вышеупомянутый метод будет хорошо работать в настройке CI, где все предыдущие миграции уже были бы проверены до того, как были включены в производство.При такой настройке имеет смысл интересоваться только тестированием новейшей миграции.^^: Для каждого метода тестирования, который проверяет эффекты миграции Up, требуется метод обратного теста, который проверяет эффекты соответствующей миграции Down.

0 голосов
/ 06 апреля 2019

Это гораздо более простой подход, чем тот, который я описал.

Arrange: используйте IMigrator.Migrate, чтобы применить все миграции, вплоть до (включая), предшествующего тому, который требует тестирования. Тогда вот ключ: используйте SqlCommand для непосредственного заполнения базы данных.

Act: применить миграцию, требующую тестирования.

Assert.

...