您可以在单元测试项目中使用 Visual Studio 数据库项目来为功能测试设置一个空数据库吗?

Posted

技术标签:

【中文标题】您可以在单元测试项目中使用 Visual Studio 数据库项目来为功能测试设置一个空数据库吗?【英文标题】:Can you use a Visual Studio Database Project in a Unit Test Project to setup a empty database for a functional test? 【发布时间】:2016-09-09 01:12:21 【问题描述】:

多年来,我们一直使用以下代码在基类中设置数据库,以便对 DAL 进行功能测试,这对我们来说非常有效。

/// <summary>
/// Initializes the test class by creating the integration database.
/// </summary>
[TestInitialize]
public virtual void TestInitialize()

    DataContext = new DataContext(ConnectionString);

    CleanupPreviousTestRunDatabases();

    if (DataContext.Database.Exists())
    
        DataContext.Database.Delete();
    

    DataContext.Database.Create();
    DataContext.Database.ExecuteSqlCommand(String.Format(Strings.CreateLoginCommand, DatabaseUserName, DatabasePassword));
    DataContext.Database.ExecuteSqlCommand(String.Format("CREATE USER 0 FOR LOGIN 0", DatabaseUserName));
    DataContext.Database.ExecuteSqlCommand(String.Format("EXEC sp_addrolemember 'db_owner', '0'", DatabaseUserName));

但是,使用 Entity Framework 并不能设置数据库的所有组件,我们希望发现 EF DAL 模型与实际数据库之间的差异。

我们使用 SSDT 工具/Visual Studio 数据库项目来完成我们所有的数据库工作,而且我知道您可以编写 SQL 单元测试,并且在那些 SQL 单元测试中,我已经看到了设置和创建基于以下数据库的数据库的能力数据库项目本身。这是我想做的,但来自我们的其他功能测试库。

我可以参考这些库并编写一些设置代码,但我正在寻找的是:

a) 我如何提供用于部署的数据库项目?

b) 如何在代码而不是 app.config 中指定连接字符串,例如使用 localdb 而不是动态命名的数据库?

namespace Product.Data.Tests

    using Microsoft.Data.Tools.Schema.Sql.UnitTesting;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class FunctionalTest
    
        [TestInitialize]
        public virtual void TestInitialize()
        
            SqlDatabaseTestClass.TestService.DeployDatabaseProject();
            SqlDatabaseTestClass.TestService.GenerateData();
        
    

SQL 单元测试项目中的 app.config 不包含对用于创建它的原始数据库项目的任何引用,并且反编译一些测试代码并查看它是如何工作的,我没有看到任何迹象.是否假设解决方案中只有一个数据库项目?

【问题讨论】:

【参考方案1】:

通过@Ed Elliott 发布的链接的一些指导,我能够做到这一点。您将需要添加 Microsoft.SqlServer.Dac 作为来自 C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\Microsoft.SqlServer.Dac.dll (Visual Studio 2015) 的程序集引用。它是 SSDT 工具的一部分,因此我确信早期版本的路径可能会有所不同。

[TestClass]
public class DatabaseTest

    protected string DatabaseConnectionString = $@"Data Source=(localdb)\v11.0; Integrated Security=True";
    protected DatabaseContext DatabaseContext;
    protected string DatabaseName = $"UnitTestDB_Guid.NewGuid().ToString("N").ToUpper()";

    public TestContext TestContext  get; set; 

    [TestInitialize]
    public virtual void TestInitialize()
    
        var instance = new DacServices(DatabaseConnectionString);
        var path     = Path.GetFullPath(Path.Combine(TestContext.TestDir, 
                                        @"..\..\..\Build\Database\Database.dacpac"));

        using (var dacpac = DacPackage.Load(path))
        
            instance.Deploy(dacpac, DatabaseName);
        

        DatabaseContext = new DatabaseContext(DatabaseConnectionString);
    

    [TestCleanup]
    public virtual void TestCleanup()
    
        DeleteDatabase(DatabaseName);
    

那么它将如何用于单元测试项目中的功能测试。

[TestClass]
public class CustomerTypeTests : DatabaseTest

    private CustomerType customerType;

    [TestInitialize]
    public override void TestInitialize()
    
        base.TestInitialize();

        customerType = new CustomerType
                       
                           Name = "Customer Type"
                       ;
    

    [TestMethod]
    public void AddOrUpdateCustomerType_ThrowExceptionIfNameIsNull()
    
        ExceptionAssert.Throws<ArgumentNullException>(() => DatabaseContext.AddOrUpdateCustomerType(customerType));
    

请注意,您还应该设置您的Build Dependencies,以便您的单元测试项目依赖于数据库项目,确保首先构建它并生成正确的dacpac 文件。

这为我们解决的问题是,它为我们提供了一个真正的数据库,而不仅仅是基于 Entity Framework 的模型,它缺少相当多的 SQL 构造(意料之中),尤其是默认约束、索引和其他重要元素的一个数据库。在我们的 DAL 层,这对我们来说至关重要。

【讨论】:

那么 DatabaseContext 是您与这些测试分开创建的自定义 EF 上下文吗?【参考方案2】:

我认为您的过程有点过于复杂(如果我理解正确的话,我可能没有!)。

我在 ssdt 中进行单元测试的目的是:

构建解决方案 将我需要的每个 dacpac 部署到我的开发实例 运行测试

要部署项目有几种方法,您可以:

为每个项目创建一个“发布配置文件”并运行它 右键单击项目并选择发布 使用 powershell 脚本(或在测试初始化​​的代码中执行)发布 dacpac。

部署后运行您的测试,从代码或脚本发布 dacpac(项目)非常简单,您可以:

调用 sqlpackage.exe 为你做这件事 使用 dacfx api 进行部署 (http://blogs.msmvps.com/deborahk/deploying-a-dacpac-with-dacfx-api/)

如果您自己控制发布,那么它会给您更多控制加上,当您使用它进行部署时,您正在测试您将在其他环境中使用的相同部署系统(假设您使用 dacpac部署)。

编辑

【讨论】:

感谢您的指导和超链接。我能够完成这项工作。

以上是关于您可以在单元测试项目中使用 Visual Studio 数据库项目来为功能测试设置一个空数据库吗?的主要内容,如果未能解决你的问题,请参考以下文章

在Visual Studio2015中使用单元测试

从单元测试生成管理器报告(Visual Studio)

无法在 Visual Studio 2017 中构建我的单元测试项目

在 Visual Studio 2013 中使用 HttpClient 进行单元测试/集成测试 Web API

Qt:使用 Visual Studio 进行单元测试

如何在Visual Studio项目和单元测试项目之间建立联系?