Подтвердить что ты не робот

Повторное создание и повторное использование LocalDb перед каждым Unit Test

Я пытаюсь написать тесты unit/integration для моего проекта ASP.NET Web API и изо всех сил пытаюсь запустить каждый тест. Позвольте мне объяснить.

У меня есть файл *.testsettings с настройками развертывания. Перед каждым тестовым запуском в тестовое место развертывается пустой файл *.mdf. Поскольку я использую Entity Framework Code First, я могу использовать инициализатор базы данных, чтобы подтолкнуть мою схему к базе данных и выровнять конкретную таблицу с двумя строками. Это отлично работает.

Проблема, с которой я сталкиваюсь, заключается в том, что различные тесты для всех моих действий ApiControllers могут наступать друг на друга, если они выполняются в неправильном порядке. Например, если я запускаю тест GET перед тестом POST, тогда GET возвращает 2 объекта, если они выполняются в обратном порядке, тогда GET возвращает 3 объекта.

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

4b9b3361

Ответ 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