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

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

如果您使用此方法,则可以在测试结束之后回滚在测试过程中执行的任何更改。下面的过程说明了具体的做法:在使用 BEGIN TRANSACTION 和ROLLBACK TRANSACTION 的Transact-SQL 测试脚本中创建事务。为某个测试类中的单个测试方法创建一个事务。为给定测试类中的所有测试方法创建一个事务。系统必备组件对于本主题中的某些过程,运行单元测试的计算机必须正在运行 Distributed Transaction Coordinator 服务。有关更多信息,请参见本主题末尾的过程。使用Transact-SQL 创建事务使用Transact-SQL 创建事务在数据库单元测试设计器中打开单元测试。指定要创建事务的脚本类型。例如,可以指定预先测试、测试或后期测试。在Transact-SQL 编辑器中输入测试脚本。插入BEGIN TRANSACTION 和ROLLBACK TRANSACTION 语句,如下面的简单示例所示。此示例使用名为 OrderDetails 并包含 50 行数据的数据库表:BEGIN TRANSACTION TestTransaction UPDATE "OrderDetails" 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 方法。为单个测试方法创建事务在“解决方案资源管理器”中,右击测试项目中的“引用”节点,然后单击“添加引用”。将显示"添加引用"对话框。单击“.NET”选项卡。在程序集列表中,单击“System.Transactions”,然后单击“确定”。打开单元测试的 Visual Basic 或 C# 文件。包装预先测试、测试和后期测试 *** 作,如下面的 Visual Basic 代码示例所示: _ 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。还必须在这些程序集中添加对项目的引用。为某个测试类中的所有测试方法创建一个事务为某个测试类中的所有测试方法创建一个事务打开单元测试的 Visual Basic 或 C# 文件。在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 服务打开“控制面板”。在“控制面板”中打开“管理工具”。在“管理工具”中打开“服务”。在“服务”窗格中,右击 “Distributed Transaction Coordinator” 服务,再单击“启动”。该服务的状态应当更新为“已启动”。现在应当能够运行那些使用 System.Transactions 的单元测试。重要事项即使您启动了分布式事务处理控制器服务,仍然可能出现以下错误:System.Transactions.TransactionManagerCommunicationException: Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool. --->System.Runtime.InteropServices.COMException: The transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D024)。如果出现此错误,您必须为网络访问配置分布式事务处理控制器。有关更多信息,请参见启用网络 DTC 访问 。

简单回答就是:不用测。原则是,除了统计类需求、业务逻辑在数据库里、数据库性能测试 这3个需求外,没有必要专门测试数据库。

很多(标准三层)项目,只写数据访问上层业务逻辑层的单元测试。因为

在某些项目,ORM框架稳定,开发规范完备的情况下,测试数据库是完全没有必要的

测试数据库很慢,很慢……

使用一些Mock工具,或者用依赖注入等方法,可以手动写一些直接返回硬编码数据的方法替换掉数据库 *** 作。相关工具如TypeMock, Rhino Mocks等。

对2.a的解释:

单独测试插入、更新方法基本上没有必要。因为数据库不会出错(基本假设),出错的主要可能是

数据库结构改变了(这种情况应该用规范数据库变动制度来完成约束)

SQL语句写错了(一般使用稳定的ORM框架能避免大部分此类错误,所以不用测;第1条里描述的情况除外)

如果非要测,可以考虑使用专门的数据库测试工具,VS里就自带了一个。自己写的话挺麻烦的。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/6696585.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-26
下一篇 2023-03-26

发表评论

登录后才能评论

评论列表(0条)

保存