2

我为调用我的 SQL Server 的 .net 代码编写了一些测试。看来 usingSystem.Transactions是回滚对数据库所做的任何修改的绝佳选择。我知道一些纯粹主义者会建议我可能想模拟数据库,但我不会走那条路;这不是严格意义上的纯单元测试。

当我编写并运行几个测试时,这完全符合预期。我只是将用于初始化和中止 .net 事务的代码放在测试设置和测试拆卸方法中。这似乎是一个很好的解决方案。

但是,我遇到的问题是,当我尝试运行 100 个这样的测试时,它们中的许多会抛出异常,即使它们在一个接一个运行时通过,它们也无法连接到 SQL Server。更糟糕的是,当我运行测试时,我的数据库中的表有时会偶尔被锁定。我必须让我的 DBA 手动移除锁。

许多人都知道,在针对 SQL 服务器的开发工作站上运行的代码(如运行此测试)上使用 TransactionScope 将使 .net 框架使用 MSDTC。

这是一个代码示例来说明我在做什么:

 <TestInitialize()> Public Sub MyTestInitialize()
    _scope = New System.Transactions.TransactionScope( _
        System.Transactions.TransactionScopeOption.Required, New TimeSpan(0, 2, 0))
End Sub
<TestCleanup()> Public Sub MyTestCleanup()
    _scope.Dispose()
End Sub

<TestMethod()> Public Sub CurrentProgramUser_Get_UserID()
    Dim ProgramSessionId As String
    Dim CurrentProgramUserId As Integer
    Dim dSession As ProgramSession
    CurrentDCMAUserId = Convert.ToInt32( _
    SqlHelper.ExecuteScalar(testDcmaConnString, System.Data.CommandType.Text, _
    "INSERT into Program_Users(UserName,FirstName,LastName) " & _
    "VALUES('GuitarPlayer','Bob','Marley')" & _
    "SELECT IDENT_CURRENT('Program_users') ") _
                         )
    ProgramSessionId = session.getCurrentSession()
    session.WriteUserParam("Program", ProgramSessionId, "USERID", CurrentProgramUserId.ToString(), testSource, testConnString)

    Dim readValue As Integer
    readValue = session.User.UserID

    Assert.AreEqual(CurrentProgramUserId, readValue)
End Sub

如您所见,这里没有什么特别花哨的。我只有一个测试方法,它将向我的数据库写入一些我希望我的方法找到的东西。这只是一个例子;还有很多其他类似的测试。

我的测试逻辑似乎是合理的。什么可能导致我的测试不仅失败,而且偶尔将用户锁定在表之外?

4

1 回答 1

2

我发现了问题。我正在测试的一种方法使用了一个SqlDataReader对象。显然,Close()必须在SqlDataReader超出范围之前调用该方法才能释放连接,但就我而言,我没有这样做。

只需添加mySqlDataReader.Close()到被测方法的末尾即可解决问题。此外,测试这个特定方法的测试方法是数据驱动的,有超过 100 个测试用例,所以这解释了我是如何用完连接的。

于 2010-06-21T19:22:48.347 回答