如何使用每个MSTest单元测试运行的新数据库实例

时间:2011-07-07 01:14:14

标签: visual-studio-2010 ado.net mstest sql-server-express

我在Visual Studio 2010下使用MSTest来测试ASP.NET MVC 3项目。我有一个我希望它使用的SQL Express 2005数据库,我每次都需要一个新的DB实例,从我已包含在项目中的模板中复制。我会有相当标准的要求,但我不能让它发挥作用。

我创建了一个.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'.

this MSDN thead中接受的答案表示删除“Database =”连接字符串参数。但是,如果我这样做,则会因此错误而失败:

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

如何让它发挥作用?

1 个答案:

答案 0 :(得分:1)

到目前为止,我已经想出了一个hack来在运行时更改数据库名称,在测试程序集初始化时。这需要进一步的破解 - 使用Reflection来启用在运行时修改配置(thanks to 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(),否则会遗留数据以前的测试。