0

当我运行它时,我的一个单元测试似乎随机通过或失败。为什么会发生这种情况对我来说唯一有意义的是每次运行测试时数据库中的数据是否进入不同的状态,但我在每次测试中使用事务来回滚数据库 - 除非它不能正常工作. 这是我的基本单元测试类和有问题的单元测试类。你能看到我可能遗漏的任何东西或我应该寻找的其他东西吗?

TestDriven.NetVisual Studio 单元测试框架会发生这种情况。

Partial Public MustInherit Class TestBase

    Private _scope As Transactions.TransactionScope

    <DebuggerStepThrough()> _
    <TestInitialize()> _
    Public Sub Setup()

            //'Start the Distribution Transaction Coordinator, if it's not already running.
            Using dtcService As New System.ServiceProcess.ServiceController("Distributed Transaction Coordinator", My.Computer.Name)
                    If dtcService.Status = ServiceProcess.ServiceControllerStatus.Stopped Then
                            dtcService.Start()
                    End If
            End Using

            _scope = New TransactionScope(TransactionScopeOption.RequiresNew, New TimeSpan(0))
    End Sub

    <DebuggerStepThrough()> _
    <TestCleanup()>
    Public Sub Teardown()
        If _scope IsNot Nothing Then
            _scope.Dispose()
        End If
    End Sub

    <System.Diagnostics.DebuggerStepThrough()> _
    Public Shared Function ExecSql(ByVal sql As String) As System.Data.DataTable

        Dim connStr = GlobalSettings.GetConnectionString()
        Using conn As New System.Data.SqlClient.SqlConnection(connStr)
            conn.Open()

            Dim cmd As New System.Data.SqlClient.SqlCommand(sql.ToString, conn)
            Dim adapter As System.Data.SqlClient.SqlDataAdapter = New System.Data.SqlClient.SqlDataAdapter(cmd)
            Dim dt As System.Data.DataTable = New System.Data.DataTable
            adapter.Fill(dt)

            Return dt

            If conn.State <> System.Data.ConnectionState.Closed Then
                conn.Close()
            End If
            conn.Dispose()
        End Using
    End Function
End Class

这是我的单元测试:

Partial Public Class CampaignEmailSendLimitServiceTests
    Inherits TestBase

    Private _service = ServiceManager.Current.MyService

    <TestMethod()> _
    Public Sub MyTest()
        //' Set the pre-test condition.
        ExecSql("update base.dbo.tblTableA set someDate = '2010-06-28' where id = 56937 ")

        //' Run the service
        _service.Process()

       //' Verify the expected result
       Dim dt = ExecSql("select deliveryDate from tblTableB ")
       Assert.AreEqual(False, dt.Rows(0).IsNull("deliveryDate"))

    End Sub
End Class
4

3 回答 3

1

这对我来说一直很好。我看到的主要区别是使用 TransactionScopeOption.Required。

[TestClass()]
public class MyTest: DatabaseTestClass
{

    public MyTest()
    {
        InitializeComponent();
    }

    TransactionScope ambientTransaction;

    [TestInitialize()]
    public void TestInitialize()
    {
        ambientTransaction = new TransactionScope(TransactionScopeOption.Required);
        base.InitializeTest();
    }

    [TestCleanup()]
    public void TestCleanup()
    {
        ambientTransaction.Dispose();
        base.CleanupTest();
    }
}
于 2011-05-16T19:12:58.140 回答
0

为什么要使用 DataAdapter.Fill 来执行更新?它旨在用 select 语句填充 DataTables。

我的猜测是,您一开始并没有使用 ExecSql 向数据库写入任何内容。

第二件事。该断言尽可能不可读。我会改变

Assert.AreEqual(False, dt.Rows(0).IsNull("deliveryDate"));

Assert.IsFalse(dt.Rows(0).IsNull("deliveryDate"));

或者

Assert.That(dt.Rows(0)("deliveryDate"), Is.Not.Null));

不可读的测试是一些人说单元测试不好的原因之一,因为它会减慢你的速度。您必须使单元测试尽可能易于阅读和理解。这样他们就没有反对单元测试的论据;)

由于我不使用 VB.NET,可能会有一些错别字。断言示例来自 NUnit。

于 2011-05-16T21:44:13.497 回答
0

我终于弄清楚发生了什么。它与交易无关。这一切都很好。是我的过程造成了不一致的行为——设计使然。如果没有找到其他排名,则该过程的一部分具有“随机排名”来确定交付日期。单元测试需要重写以更好地反映业务规则。

于 2011-05-17T16:29:50.087 回答