我在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.
如何让它发挥作用?
答案 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()
,否则会遗留数据以前的测试。