【问题标题】:vb.net mocking dal methods with moqvb.net 用 moq 模拟 dal 方法
【发布时间】:2011-10-25 22:04:19
【问题描述】:

我想知道您是否可以帮助我理解最小起订量的概念...我有一种方法要测试。它包含我要模拟的数据访问方法。

测试方法:

Public Function GetReport(ByVal district As String, ByVal hub As String, ByVal dateFrom As Date, ByVal dateTo As Date, ByVal response As HttpResponse) As String
        Dim msg As String = String.Empty
        Dim rs As New ReportingService

        _dt = _dal.GetData(district, hub, dateFrom, dateTo)

        If _dt.Rows.Count <= 0 Then
            msg = "There were no records found for the selected criteria."
        ElseIf _dt.Rows.Count + 1 > 65536 Then
            msg = "Too many rows - Export to Excel not possible."
        Else
            rs.Export(_dt, "AcceptanceOfOffer", response)
        End If

        Return msg
    End Function 

我想测试控制逻辑。如果数据表有 0,1 或多行,则应返回不同的消息。我不关心 _dal.GetData 的结果,这是我希望模拟的方法。

这是我的测试,没有 nunit 或类似的东西:

'''<summary>
'''A test for GetReport
'''</summary>
<TestMethod()> _
Public Sub GetReportTest()
    'Create a fake object
    Dim mock = New Mock(Of IAcceptanceOfferDAL)
    'Create the real data to be returned by the fake
    Dim returnDt As DataTable = New DataTable()
    returnDt.Columns.Add("District", Type.GetType("System.String"))
    returnDt.Columns.Add("Hub", Type.GetType("System.String"))
    returnDt.Columns.Add("dateFrom", Type.GetType("System.DateTime"))
    returnDt.Columns.Add("dateTo", Type.GetType("System.DateTime"))
    returnDt.Rows.Add("District", "Hub", Date.Today, Date.Today)

    'Setup the fake so that when the method is called the data created above will be returned
    mock.Setup(Function(f) f.GetData(It.IsAny(Of String), It.IsAny(Of String), It.IsAny(Of Date), It.IsAny(Of Date))).Returns(returnDt)

    'Call the real method with the expectation that when it calls GetData it will use our mock object
    Dim target = New AcceptanceOfferBLL

    Dim response As HttpResponse
    Dim actual = target.GetReport("district", "hub", Date.Today, Date.Today, response)
    'Because our mock returns 1 row it will skip over our if statements and should return string.empty
    Assert.AreEqual("", actual)

End Sub

以防万一,我试图模拟的 DAL 类和方法。

Public Interface IAcceptanceOfferDAL
    Function GetData(ByVal district As String, ByVal site As String, ByVal dateFrom As Date, ByVal dateTo As Date) As DataTable
End Interface

Public Class AcceptanceOfferDAL : Implements IAcceptanceOfferDAL
    Private _ds As New DataService.DataAccess
    Private _sNameSP As String = ""
    Private _listSQLParams As New List(Of SqlParameter)

    Public Function GetData(ByVal district As String, ByVal site As String, ByVal dateFrom As Date, ByVal dateTo As Date) As DataTable Implements IAcceptanceOfferDAL.GetData
        _sNameSP = "up_AcceptanceHub_get"

        Dim sqlParam As SqlParameter = New SqlParameter("@district", district)
        Dim sqlParam1 As SqlParameter = New SqlParameter("@hub", site)
        Dim sqlParam2 As SqlParameter = New SqlParameter("@DateFrom", dateFrom)
        Dim sqlParam3 As SqlParameter = New SqlParameter("@DateTo", dateTo)

        _listSQLParams.Add(sqlParam)
        _listSQLParams.Add(sqlParam1)
        _listSQLParams.Add(sqlParam2)
        _listSQLParams.Add(sqlParam3)

        Return (_ds.LoadDataTableByID(_listSQLParams, _sNameSP))

    End Function

End Class

显然这不起作用,我检查了起订量快速入门和其他 places 没有成功。这甚至可能还是我应该使用 .verify 或其他东西? This post 具有我想要使用的结构,除非在这种情况下,模拟对象作为参数传递给方法。

【问题讨论】:

  • 你能澄清一下“这不起作用”是什么意思吗?
  • 代码转到真正的具体 dal.GetData 方法,而不是该方法的代理版本。它尝试连接到数据库并返回信息,而不是我在测试中创建的虚拟数据集。
  • 您永远不会将模拟 IAcceptanceOfferDAL 传递给 AcceptanceOfferBLL。 AcceptanceOfferBLL 的“_dal”变量是如何创建的?它应该是在运行时通过 IOC 容器注入的构造函数依赖项,但在测试期间被模拟。
  • 依赖注入是唯一的选择吗?你能解释一下除了让测试正常工作之外的好处吗?
  • 使用带有依赖注入的 IoC 容器有很多好处——尤其是在可测试性方面。一些谷歌搜索“控制模式反转”会产生很多结果。

标签: vb.net unit-testing moq


【解决方案1】:

GetReport 方法依赖于在GetReport 方法之外定义的_dal

因此,尽管为IAcceptanceOfferDAL 创建了一个模拟对象,但该模拟对象并没有发挥作用,因为GetReport 只知道使用在其他地方实例化的_dal 对象。

要绕过这种依赖关系,需要将_dal 对象作为参数传递到方法中。

Public Function GetReport(ByVal district As String
                        , ByVal hub As String
                        , ByVal dateFrom As Date
                        , ByVal dateTo As Date
                        , ByVal response As HttpResponse
                        , ByVal _dal As IAcceptanceOfferDAL) As String

通过这样做,IAcceptanceOfferDAL 的模拟及其GetData 函数的设置将在测试GetReport 方法时发挥作用,如下所示:

Dim actual =  target.GetReport("district"
                             , "hub"
                             , Date.Today
                             , Date.Today
                             , response
                             , mock)

因此,需要明确的是,更改GetReport 方法使其接受IAcceptanceOfferDAL 的实例作为参数允许在测试时将模拟对象传递到此方法,并且能够传入该模拟,当然,提供对GetData 方法的返回值的所需控制。

希望对你有帮助

【讨论】:

  • 太棒了。这肯定适用于测试,但必须以这种方式更改代码以便我可以测试它似乎有点......我不知道,错了吗?
  • 我认为这是思维方式的改变:任何会引入对方法的依赖的对象或服务都应该由接口引用,并且该接口应该作为参数传递给方法。这允许单元测试传递对象或服务的模拟,而对应用程序中方法的调用将传递实现相同接口的对象或服务的实例,并完成单元测试需要避免的依赖关系。
猜你喜欢
  • 2010-11-12
  • 2011-01-18
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
相关资源
最近更新 更多