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

发布于 2024-11-18 23:18:02 字数 1344 浏览 5 评论 0原文

我在 Visual Studio 2010 下使用 MSTest 来测试 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.

如何让它工作?

I'm using MSTest under Visual Studio 2010 to test an ASP.NET MVC 3 project. I have a SQL Express 2005 DB that I'd like it to use and I want a fresh instance of the DB every time, copied from a template I've included in the project. Pretty standard requirements, I would have though, but I can't get this to work.

I've created a .testsettings file which enables deployment and my connection string looks like this:

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

The test runs OK the first time, but after that it fails with errors like this:

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'.

The accepted answer in this MSDN thead says to remove the "Database=" connection string parameter. However, if I do that it fails with this error:

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

How do I get this to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岛徒 2024-11-25 23:18:02

到目前为止,我已经想出了一种在运行时、测试程序集初始化时更改数据库名称的方法。这需要进一步的破解 - 使用反射来启用在运行时修改配置(感谢大卫·加德纳)。

[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(),否则它获取先前测试留下的数据。

So far I've come up with a hack to change the DB name at runtime, at test assembly initialization time. This requires a further hack - using Reflection to enable modifying the configuration at runtime (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());
    }
}

Edit: It's actually even a bit worse than this: I'm having to call TestHelper.RandomizeDbName() at the start of every test that requires a fresh DB, otherwise it gets data left over from previous tests.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文