在VB.NET中用NSubstitute引发事件

时间:2018-10-05 22:49:47

标签: vb.net unit-testing nsubstitute

使用VB.NET和NSubstitute在单元测试中引发事件时遇到麻烦。被模拟的接口定义了一个事件:

Event BlockOfVehiclesProcessed(source As Object, stats As ProcessingStats)

被测类为该事件注册一个处理程序。在单元测试中,我想引发事件,以便调用被测类中的处理程序。基于NSubstitute文档(不幸的是所有C#)以及关于Stackoverflow的各种答案,等等,我尝试了各种排列方式:

AddHandler mock.BlockOfVehiclesProcessed, Raise.EventWith(New ProcessingStats(50))

但是我还没有发现任何可以编译的东西。一条错误消息:

Value of type 'EventHandlerWrapper(...)' cannot be converted to '...BlockOfVehiclesProcessedEventHandler'

我尝试将0 args和2 args传递给EventWith(),我尝试为EventWith()显式指定arg类型,并尝试了Raise.Event(),但是我找不到创建编译器的神奇顺序快乐。有没有人举起一个活动的VB单元测试的例子?

1 个答案:

答案 0 :(得分:2)

然后的问题是,在没有显式提供事件处理程序类型的情况下声明事件时,NSubstitute不支持vb.net创建的匿名事件处理程序类型。

如果强制使用NSubstitute(并作为问题的答案),则声明显式提供的事件处理程序类型的事件将解决您的问题。

' Example with Action as event handler type
Public Interface IVehicleProcessor
    Event BlockOfVehiclesProcessed As Action(Of Object, String) 
End Interface

Public Class System
    Private ReadOnly _processor As IVehicleProcessor
    Public Property ProcessedStats As String

    Public Sub New(IVehicleProcessor processor)
        _processor = processor
        AddHandler _processor.BlockOfVehiclesProcessed, Sub(sender, stats) ProcessedStats = stats
    End Sub
End System

' Test
Public Sub ShouldNotifyProcessedStats()
    Dim fakeProcessor = Substitute.For(Of IVehicleProcessor)
    Dim system As New System(fakeProcessor)

    ' Raise an event with known event handler type
    AddHandler fakeProcessor.BlockOfVehiclesProcessed, 
        Raise.Event(Of Action(Of Object, String))(fakeProcessor, "test-stats")

    system.ProcessedStats.Should().Be("test-stats") ' Pass
End Sub

另一种方法是使用事件创建自己的虚假接口实现。我发现这种方法要好得多,只是因为您不需要更改生产代码,因为某些测试框架无法支持vb.net语言功能。

Public Class FakeVehicleProcessor
    Implements IVehicleProcessor

    Public Event BlockOfVehiclesProcessed(source As Object, stats As String) Implements IVehicleProcessor.BlockOfVehiclesProcessed

    ' Use this method to raise an event with required arguments
    Public Sub RaiseEventWith(stats As String)
        RaiseEvent BlockOfVehiclesProcessed(Me, stats)
    End Sub
End Class

' Test
Public Sub ShouldNotifyProcessedStats()
    Dim fakeProcessor As New FakeVehicleProcessor()
    Dim system As New System(fakeProcessor)

    fakeProcessor.RaiseEventWith("test-stats")

    system.ProcessedStats.Should().Be("test-stats") ' Pass
End Sub