带列表参数的Moq方法

时间:2013-12-10 13:08:59

标签: testing tdd moq

您好我遵循以下测试

    <TestInitialize()>
Public Sub Initialise()
    dbHelper = New Mock(Of IDbHelper)
    dt = New DataTable()
    dt.Columns.AddRange(New DataColumn() {New DataColumn("AreaId"),
                                          New DataColumn("Area"),
                                          New DataColumn("CountryId"),
                                          New DataColumn("Country"),
                                          New DataColumn("SubRegionId"),
                                          New DataColumn("SubRegion"),
                                          New DataColumn("RegionId"),
                                          New DataColumn("Region"),
                                          New DataColumn("Notes"),
                                          New DataColumn("Enabled"),
                                          New DataColumn("FlagIgnoreFactsheet")
                                          })
    dt.Rows.Add(New String() {"0", "", "0", "", "0", "", "0", "", "", "True", "False"})

    Dim paramList As New List(Of SqlParameter)
    paramList.Add(New SqlParameter("@AreaId", It.IsAny(Of Int64)))
    paramList.Add(New SqlParameter("@AreaName", String.Empty))
    paramList.Add(New SqlParameter("@CountryId", 0))
    paramList.Add(New SqlParameter("@Enabled", 1))
    paramList.Add(New SqlParameter("@ShowAll", 0))

    dbHelper.Setup(Function(db) db.ExecuteReader(It.IsAny(Of String), paramList)).Returns(dt)

End Sub

 <TestMethod()>
Public Sub GetAreaWithParamTest()

    Dim areaRepository As AreaRepository = New AreaRepository(dbHelper.Object)

    Dim result = areaRepository.GetArea(1)

    Assert.IsNotNull(result)
End Sub

但是测试失败了,因为dbHelper.ExecuteReader返回一个null对象而不是预期的Datatable。

然而,如果不使用params而是使用It.IsAny(List(Of SqlParameter))

以下是GetArea方法

的代码
Public Function GetArea(ByVal pAreaId As Long) As AreaEntity Implements IAreaRepository.GetArea
        MyResponse = Nothing
        If pAreaId = 0 Then Return Nothing

        Try
            Dim paramList As New List(Of SqlParameter)
            paramList.Add(New SqlParameter("@AreaId", pAreaId))
            paramList.Add(New SqlParameter("@AreaName", String.Empty))
            paramList.Add(New SqlParameter("@CountryId", 0))
            paramList.Add(New SqlParameter("@Enabled", 1))
            paramList.Add(New SqlParameter("@ShowAll", 0))

            Dim dt As DataTable = _dbHelper.ExecuteReader("sp_Core_AreaList", paramList)
            MyResponse = _dbHelper.MyResponse

            If IsNothing(dt) OrElse dt.Rows.Count = 0 Then Return Nothing

            Dim dr As DataRow = dt.Rows.Cast(Of DataRow).First()

            Dim result As AreaEntity = New AreaEntity() With {
                .AreaId = IIf(IsDBNull(dr("AreaId")), 0, dr("AreaId")),
                .AreaName = IIf(IsDBNull(dr("Area")), String.Empty, dr("Area")),
                .CountryId = IIf(IsDBNull(dr("CountryId")), 0, dr("CountryId")),
                .CountryName = IIf(IsDBNull(dr("Country")), String.Empty, dr("Country")),
                .SubRegionId = IIf(IsDBNull(dr("SubRegionId")), 0, dr("SubRegionId")),
                .SubRegionName = IIf(IsDBNull(dr("SubRegion")), String.Empty, dr("SubRegion")),
                .RegionId = IIf(IsDBNull(dr("RegionId")), 0, dr("RegionId")),
                .RegionName = IIf(IsDBNull(dr("Region")), String.Empty, dr("Region")),
                .Notes = IIf(IsDBNull(dr("Notes")), String.Empty, dr("Notes")),
                .Enabled = IIf(IsDBNull(dr("Enabled")), False, dr("Enabled")),
                .FlagIgnoreFactsheet = IIf(IsDBNull(dr("FlagIgnoreFactsheet")), False, dr("FlagIgnoreFactsheet"))
            }

            Return result
        Catch ex As Exception
            MyResponse = New Response("AreaRepository.GetArea", "Error while loading area information", ex)
            Return Nothing
        End Try

    End Function

请帮助!!!!!

2 个答案:

答案 0 :(得分:0)

使用ExecuteReader()设置dbHelper.Setup(Function(db) db.ExecuteReader(It.IsAny(Of String), paramList)).Returns(dt)方法时,它希望paramList作为参数传递。但实际上你传递另一个对象,但结构相同。

MOQ通过引用比较List您也可能面临与Expression相同的问题。我已经回答了问题Why this mock with Expression is not matching?

我建议您使用ExecuteReader()设置It.IsAny(Of List(Of SqlParameter))方法,然后使用 Callbacks 验证参数列表

在GitHub中使用Callbacks的例子如下:

mock.Setup(foo => foo.Execute(It.IsAny<int>(), It.IsAny<string>()))
    .Returns(true)
    .Callback<int, string>((i, s) => 
        {
            /* your asserts can be placed here */
        });

答案 1 :(得分:0)

我发现这个链接在我的场景中非常有用

http://www.codeproject.com/Articles/47603/Mock-a-database-repository-using-Moq