Повторное создание и повторное использование LocalDb перед каждым Unit Test
Я пытаюсь написать тесты unit/integration для моего проекта ASP.NET Web API и изо всех сил пытаюсь запустить каждый тест. Позвольте мне объяснить.
У меня есть файл *.testsettings с настройками развертывания. Перед каждым тестовым запуском в тестовое место развертывается пустой файл *.mdf. Поскольку я использую Entity Framework Code First, я могу использовать инициализатор базы данных, чтобы подтолкнуть мою схему к базе данных и выровнять конкретную таблицу с двумя строками. Это отлично работает.
Проблема, с которой я сталкиваюсь, заключается в том, что различные тесты для всех моих действий ApiControllers могут наступать друг на друга, если они выполняются в неправильном порядке. Например, если я запускаю тест GET перед тестом POST, тогда GET возвращает 2 объекта, если они выполняются в обратном порядке, тогда GET возвращает 3 объекта.
Мне кажется, что мне нужно сделать, это сбросить, воссоздать и обновить мою базу данных до каждого теста. Это хорошая идея или есть лучший способ? Если это лучшее, что я могу сделать, я бы пошел на перезагрузку моей базы данных перед каждым тестом.
Ответы
Ответ 1
Вот что я сделал для всех, кого это интересует.
Я расширил DropCreateDatabaseAlways<TContext>
и переопределил метод Seed, чтобы заполнить мою базу данных известными тестовыми данными, на которые могут положиться мои модульные тесты.
public class MyDatabaseInitializer : System.Data.Entity.DropCreateDatabaseAlways<MyDbContext>
{
protected override void Seed(MyDbContext context)
{
// Add entities to database.
context.SaveChanges();
}
}
Затем я реализовал метод [AssemblyInitialize]
, который устанавливает инициализатор базы данных.
[TestClass]
public class Global
{
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
System.Data.Entity.Database.SetInitializer(new MyDatabaseInitializer());
}
}
Это устанавливает инициализатор для базы данных, но фактически не запускает его. Интеритаризатор запускается в методе [TestInitialize]
, который я написал, который заставляет базу данных удаляться, воссоздаваться и повторно загружаться перед каждым тестом.
[TestClass]
public class MyTestClass
{
[TestInitialize]
public void TestInitialize()
{
MyDbContext context = new MyDbContext();
context.Database.Initialize(true);
}
[TestMethod]
public void MyUnitTest()
{
Assert.IsTrue(true);
}
}
Ответ 2
Я бы предложил повторно создать вашу базу данных, прежде чем вы начнете свои тесты, а затем оберните их каждой транзакцией, которая всегда откатывается. Это очень полезно, если на этапе повторного создания требуется много времени для завершения (например, из-за действий, которые необходимо выполнить и т.д.).
Ответ 3
В нашей текущей настройке мы воссоздаем схему базы данных перед загрузкой каждого класса (с атрибутом ClassInitialize, но это определенно можно перенести в AssemblyInitialize) и просто посеять/очистить базу данных соответствующими записями до/после каждого тестовый прогон (с атрибутом TestInitialize/TestCleanup).
Дополнительная информация: http://msdn.microsoft.com/en-us/library/ms379625(v=vs.80).aspx