如何对 VBA 代码进行单元测试? - 两个不同的指针
How to unit test VBA code? - Two different pointers
我正在研究 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
我不得不将数组指针教程中的 Long 类型更改为 LongLong,因为 64 位数字对于 Long 来说太长了。 LongPtr 也有效
VarPtr
人为地使该测试复杂化,引入了不需要存在的脆弱和有缺陷的指针逻辑。
将您的存根数据服务更改为 return 一些非空数据 - 实际上任何内容都可以:
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
正在 returning 与 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 优秀教程,但最后我的第一个测试没有通过,因为我可以清楚地看到我正在创建两个不同的数组(和指针),并尝试将它们相互比较。
现在,我所看到的教程遗漏了几行我添加的代码,这也是我看到问题的地方,但如果没有这些行,代码甚至 运行 .
我的所有其他测试方法都与示例相同,除了我创建以下行的方法 - 否则当您 运行 测试时没有任何反应。
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
我不得不将数组指针教程中的 Long 类型更改为 LongLong,因为 64 位数字对于 Long 来说太长了。 LongPtr 也有效
VarPtr
人为地使该测试复杂化,引入了不需要存在的脆弱和有缺陷的指针逻辑。
将您的存根数据服务更改为 return 一些非空数据 - 实际上任何内容都可以:
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
正在 returning 与 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
这让测试简单多了,它通过了:
我将在今天晚些时候用这个更简单的测试更新文章。