如何:编写在单个事务范围内运行的数据库单元测试

更新:2007 年 11 月

可以修改单元测试,使其在单个事务范围内运行。如果您使用此方法,则可以在测试结束之后回滚在测试过程中执行的任何更改。下面的过程说明了具体的做法:

  • 在使用 BEGIN TRANSACTION 和 ROLLBACK TRANSACTION 的 Transact-SQL (T-SQL) 测试脚本中创建事务。

  • 为某个测试类中的单个测试方法创建一个事务。

  • 为给定测试类中的所有测试方法创建一个事务。

系统必备

对于本主题中的某些过程,运行单元测试的计算机必须正在运行分布式事务协调程序服务。有关更多信息,请参见本主题末尾的过程。

使用 T-SQL 创建事务

使用 T-SQL 创建事务

  1. 在数据库单元测试设计器中打开单元测试。

  2. 指定要创建事务的脚本类型。例如,可以指定预先测试、测试或后期测试。

  3. 在 T-SQL 编辑器中输入测试脚本。

  4. 插入 BEGIN TRANSACTION 和 ROLLBACK TRANSACTION 语句,如下面的简单示例所示。此示例使用包含 50 行数据的 Northwind 数据库表:

    BEGIN TRANSACTION TestTransaction
    UPDATE "Order Details" set Quantity = Quantity + 10
    IF @@ROWCOUNT!=50
    RAISERROR('Row count does not equal 50',16,1)
    ROLLBACK TRANSACTION TestTransaction
    
    说明:

    在执行 COMMIT TRANSACTION 语句之后不能对事务进行回滚。

有关 ROLLBACK TRANSACTION 如何与存储过程和触发器一起使用的更多信息,请参见 Microsoft 网站 上的“ROLLBACK TRANSACTION (Transact-SQL)”。

为单个测试方法创建事务

在该示例中,在使用 TransactionScope 类型时,会使用环境事务。默认情况下,“执行连接”和“特权连接”将不使用环境事务,因为这些连接是在执行该方法之前创建的。SqlConnection 具有一个 EnlistTransaction 方法,该方法将活动连接与某个事务相关联。环境事务在创建之后会自行注册为当前的事务,您可以通过 Current 属性来访问它。在该示例中,环境事务在释放之后进行回滚。如果要提交在运行单元测试时进行的任何更改,则必须调用 Complete 方法。

为单个测试方法创建事务

  1. 打开单元测试的 Visual Basic 或 C# 文件。

  2. 包装预先测试、测试和后期测试操作,如下面的 Visual Basic 代码示例所示:

        <TestMethod()> _
        Public Sub dbo_InsertTable1Test()
    
            Using ts as New System.Transactions.TransactionScope( System.Transactions.TransactionScopeOption.Required)
                ExecutionContext.Connection.EnlistTransaction(Transaction.Current)
                PrivilegedContext.Connection.EnlistTransaction(Transaction.Current)
    
                Dim testActions As DatabaseTestActions = Me.dbo_InsertTable1TestData
                'Execute the pre-test script
                '
                System.Diagnostics.Trace.WriteLineIf((Not (testActions.PretestAction) Is Nothing), "Executing pre-test script...")
                Dim pretestResults() As ExecutionResult = TestService.Execute(Me.PrivilegedContext, Me.PrivilegedContext, testActions.PretestAction)
                'Execute the test script
    
                System.Diagnostics.Trace.WriteLineIf((Not (testActions.TestAction) Is Nothing), "Executing test script...")
                Dim testResults() As ExecutionResult = TestService.Execute(ExecutionContext, Me.PrivilegedContext, testActions.TestAction)
    
                'Execute the post-test script
                '
                System.Diagnostics.Trace.WriteLineIf((Not (testActions.PosttestAction) Is Nothing), "Executing post-test script...")
                Dim posttestResults() As ExecutionResult = TestService.Execute(Me.PrivilegedContext, Me.PrivilegedContext, testActions.PosttestAction)
    
                'Because the transaction is not explicitly committed, it
                'is rolled back when the ambient transaction is 
                'disposed.
                'To commit the transaction, remove the comment delimiter
                'from the following statement:
                'ts.Complete()
    
        End Sub
        Private dbo_InsertTable1TestData As DatabaseTestActions
    
    说明:

    如果使用的是 Visual Basic,则除了 Imports Microsoft.VisualStudio.TestTools.UnitTesting、Imports Microsoft.VisualStudio.TeamSystem.Data.UnitTesting 和 Imports Microsoft.VisualStudio.TeamSystem.Data.UnitTest.Conditions,还必须添加 Imports System.Transactions。如果使用的是 Visual C#,则除了 Microsoft.VisualStudio.TestTools、Microsoft.VisualStudio.TeamSystem.Data.UnitTesting 和 Microsoft.VisualStudio.TeamSystem.Data.UnitTesting.Conditions 的 using 语句,还必须添加 using System.Transactions。还必须在这些程序集中添加对项目的引用。

为某个测试类中的所有测试方法创建一个事务

为某个测试类中的所有测试方法创建一个事务

  1. 打开单元测试的 Visual Basic 或 C# 文件。

  2. 在 TestInitialize 中创建事务,并在 TestCleanup 中释放它,如下面的 Visual C# 代码示例所示:

    TransactionScope _trans;
    
            [TestInitialize()]
            public void Init()
            {
                _trans = new TransactionScope();
                base.InitializeTest();
            }
    
            [TestCleanup()]
            public void Cleanup()
            {
                base.CleanupTest();
                _trans.Dispose();
            }
    
            [TestMethod()]
            public void TransactedTest()
            {
                DatabaseTestActions testActions = this.DatabaseTestMethod1Data;
                // Execute the pre-test script
                // 
                System.Diagnostics.Trace.WriteLineIf((testActions.PretestAction != null), "Executing pre-test script...");
                ExecutionResult[] pretestResults = TestService.Execute(this.PrivilegedContext, this.PrivilegedContext, testActions.PretestAction);
                // Execute the test script
                // 
                System.Diagnostics.Trace.WriteLineIf((testActions.TestAction != null), "Executing test script...");
                ExecutionResult[] testResults = TestService.Execute(this.ExecutionContext, this.PrivilegedContext, testActions.TestAction);
                // Execute the post-test script
                // 
                System.Diagnostics.Trace.WriteLineIf((testActions.PosttestAction != null), "Executing post-test script...");
                ExecutionResult[] posttestResults = TestService.Execute(this.PrivilegedContext, this.PrivilegedContext, testActions.PosttestAction);
    
            }
    

启动 Distributed Transaction Coordinator 服务

本主题中的某些过程使用 System.Transactions 程序集内的类型。在按照这些过程操作之前,必须确保要运行单元测试的计算机上正在运行 Distributed Transaction Coordinator 服务。否则,测试将失败,并出现下面的错误消息:“测试方法 项目名称.测试名称.方法名称 引发异常: System.Data.SqlClient.SqlException: 服务器‘计算机名称’上的 MSDTC 不可用”。

启动 Distributed Transaction Coordinator 服务

  1. 打开“控制面板”。

  2. 在“控制面板”中打开“管理工具”。

  3. 在“管理工具”中打开“服务”。

  4. 在“服务”窗格中,右击“分布式事务处理协调器”服务,再单击“启动”。

    该服务的状态应当更新为“已启动”。现在应当能够运行那些使用 System.Transactions 的单元测试。