Как использовать новый экземпляр базы данных при каждом запуске модульного теста MSTest - PullRequest
2 голосов
/ 07 июля 2011

Я использую MSTest под Visual Studio 2010 для тестирования проекта ASP.NET MVC 3. У меня есть БД SQL Express 2005, которую я хотел бы использовать, и я хочу каждый раз обновлять экземпляр БД, скопированный из шаблона, который я включил в проект. Довольно стандартные требования, но я не могу заставить это работать.

Я создал файл .testsettings, который разрешает развертывание, и моя строка подключения выглядит следующим образом:

<add name="MyDb" connectionString="Data Source=.\SQLEXPRESS2005;Database=MyDbTest;AttachDBFilename=|DataDirectory|MyDbTest.mdf;User Instance=true;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />

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

Test method ... threw exception:  System.Data.DataException: An exception occurred while initializing the database. See the InnerException for details. ---> System.Data.EntityException: The underlying provider failed on Open.
---> System.Data.SqlClient.SqlException: Database '...\bin\Debug\MyDbTest.mdf' already exists. Choose a different database name. Cannot attach the file '...\Out\MyDbTest.mdf' as database 'MyDbTest'.

Принятый ответ в этой MSDN thead говорит об удалении параметра строки подключения «Database =». Однако, если я это сделаю, то произойдет сбой с этой ошибкой:

Test method ... threw exception: 
System.InvalidOperationException: Unable to complete operation. The supplied SqlConnection does not specify an initial catalog.

Как мне заставить это работать?

1 Ответ

1 голос
/ 07 июля 2011

До сих пор я придумал способ изменить имя БД во время выполнения, во время инициализации тестовой сборки. Это требует дальнейшего взлома - использование Reflection для включения возможности изменения конфигурации во время выполнения ( благодаря David Gardiner ).

[TestClass]
public static class TestHelper
{
    [AssemblyInitialize]
    public static void AssemblyInit(TestContext context)
    {
        RandomizeDbName();
    }

    private static void RandomizeDbName()
    {
        // Get the DB connection string setting
        var connStringSetting = ConfigurationManager.ConnectionStrings["TheDbSetting"];

        // Hack it using Reflection to make it writeable
        var readOnlyField = typeof(ConfigurationElement).GetField("_bReadOnly",
            BindingFlags.Instance | BindingFlags.NonPublic);
        readOnlyField.SetValue(connStringSetting, false);

        // Randomize the DB name, so that SQL Express doesn't complain that it's already in use
        connStringSetting.ConnectionString = connStringSetting.ConnectionString.Replace(
            "Database=MyTestDb", "Database=MyTestDb_" + new Random().Next());
    }
}

Редактировать: Это даже немного хуже, чем это: мне нужно вызывать TestHelper.RandomizeDbName() в начале каждого теста, который требует свежую БД, в противном случае он получает данные, оставшиеся от предыдущих тестов .

...