2011-10-25 96 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