如何对VBA代码进行单元测试? - 两个不同的指针

时间:2018-04-25 13:36:13

标签: vba unit-testing rubberduck

我正在研究this优秀的教程,但最后我的第一个测试没有通过,因为我可以清楚地看到我正在创建两个不同的数组(和指针),并试图比较他们彼此。

现在我可以看到的教程留下了我添加的几行代码,这也是我看到问题的地方,但没有这些代码甚至没有粗略的代码。

我的所有其他测试方法都与示例相同,除了我创建以下行的方法 - 否则在运行测试时没有任何反应。

Public Sub Run(ByVal dataService As IDataService, ByVal wsService As IWorksheetService)
Dim data As Variant                   'Added this line
data = dataService.GetSomeTable       'Added this line
Call wsService.WriteAllData(data)     'Added this line
End Sub

这是我可以看到代码向南的地方......

'@TestMethod
Public Sub WorksheetServiceWorksOffDataFromDataService()
    'Arrange
    Dim dataServiceStub As MyDataServiceStub
    Set dataServiceStub = New MyDataServiceStub
    Dim expected As LongLong
    expected = VarPtr(dataServiceStub.GetSomeTable)  'expected creates an Array

Dim wsServiceStub As MyWorksheetServiceStub
Set wsServiceStub = New MyWorksheetServiceStub

'Act
With New MyTestableMacro
    .Run dataServiceStub, wsServiceStub 'here we create a second array
End With

Dim actual As LongLong
actual = wsServiceStub.WrittenArrayPointer 'here we point to the address of the second array

'Assert
Assert.AreEqual expected, actual  ' this test fails cause it points to two different addresses
End Sub

由于64位的数字对于Long来说太长,我必须从Long指向LongLong的数组指针的教程中改变类型。 LongPtr也工作了

1 个答案:

答案 0 :(得分:3)

VarPtr是人为地使该测试复杂化的原因,引入了不需要存在的脆弱和有缺陷的指针逻辑。

更改您的存根数据服务以返回一些非空数据 - 实际上任何事情都可以:

Option Explicit
Implements IDataService
'@Folder "Services.Stubs"

Private Function IDataService_GetSomeTable() As Variant
    IDataService_GetSomeTable = GetSomeTable
End Function

Public Function GetSomeTable() As Variant
    Dim result(1 To 50, 1 To 10) As Variant
    result(1, 1) = "test"
    GetSomeTable = result
End Function

现在更改存根工作表服务以保留实际数据的副本(而不仅仅是LongPtr):

Option Explicit
Implements IWorksheetService
'@Folder "Services.Stubs"

Private Type TStub
    WasWritten As Boolean
    WrittenData As Variant
End Type
Private this As TStub

Private Sub IWorksheetService_WriteAllData(ByRef data As Variant)
    this.WasWritten = True
    this.WrittenData = data
End Sub

Public Property Get DataWasWritten() As Boolean
    DataWasWritten = this.WasWritten
End Property

Public Property Get WrittenData() As Variant
    WrittenData = this.WrittenData
End Property

现在更改测试以声明IDataService.GetSomeTable正在返回 IWorksheetService.WriteAllData使用的相同数据 - 您可以使用Assert.SequenceEquals执行此操作,两个数组的元素,如果有什么不同则会失败:

'@TestMethod
Public Sub WorksheetServiceWorksOffDataFromDataService()
    'Arrange
    Dim dataServiceStub As StubDataService
    Set dataServiceStub = New StubDataService
    Dim expected As Variant
    expected = dataServiceStub.GetSomeTable

    Dim wsServiceStub As StubWorksheetService
    Set wsServiceStub = New StubWorksheetService

    'Act
    With New Macro
        .Run dataServiceStub, wsServiceStub
    End With

    Dim actual As Variant
    actual = wsServiceStub.WrittenData

    'Assert
    Assert.SequenceEquals expected, actual
End Sub

这使得测试变得更加简单,并通过了:

this github issue

我将在今天晚些时候通过这个更简单的测试更新文章。