2011-10-25 73 views
1

我想知道如果你能帮助我理解moq概念......我有一个我想测试的方法。它包含我想模拟的数据访问方法。vb.net嘲讽dal方法与moq

的方法进行测试:

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具有我想要使用的结构,除非在这种情况下,模拟对象作为参数传递给方法。

+0

您能否澄清“这不起作用”的含义? – PatrickSteele

+0

代码转到真正的具体dal.GetData方法,而不是该方法的代理版本。它试图连接到数据库并返回信息,而不是我在测试中创建的虚拟数据集。 – Andrew

+0

你永远不会将模拟IAcceptanceOfferDAL传递给AcceptanceOfferBLL。 AcceptanceOfferBLL的“_dal”变量是如何创建的?它应该是一个构造函数依赖项,它在运行时通过IOC容器注入,但在测试期间被模拟。 – PatrickSteele

回答

0

GetReport方法取决于_dal,该方法在GetReport方法之外定义。

因此,尽管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的实例作为参数,允许在测试时将模拟对象传递到此方法中,并且传递该模拟的能力当然可以提供对方法返回值的所需控制。

希望这会有所帮助

+0

太好了。这肯定会用于测试,但必须以这种方式更改代码,以便我可以测试它似乎有点...我不知道,错了? – Andrew

+0

我认为这是一种思维方式的改变:任何对方法引入依赖的对象或服务都应该被一个接口引用,并且该接口应该作为参数传递给方法。这允许单元测试传递对象或服务的模拟,而对应用程序中的方法的调用将传递实现相同接口的对象或服务的实例,并完成单元测试需要避免的依赖关系。 – jimmym715