如何从接口派生的类的Fake实例中引发事件

时间:2016-03-22 09:19:09

标签: .net nsubstitute

正在测试的代码

Public Class ObservableName
    Implements INotifyPropertyChanged

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub RaisePropertyChanged(propertyName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub

    Private _Name as String
    Public Property Name As String
        Get
            Return _Name
        End Get
        Set(value As String)
            _Name = value
            Me.RaisePropertyChanged(NameOf(Me.Name))
        End Set
    End Property
End Class

Public Class ViewModel
    Public ReadOnly Property MyName As ObservableName
    Public Property CountOfChanges As Integer

    Public Sub New(name As ObservableName)
        Me.MyName = name
        AddHandler Me.MyName.PropertyChanged, AddressOf Me.MyName_PropertyChanged
    End Sub

    Protected Sub MyName_PropertyChanged(sender as Object, e As PropertyChangedEventArgs)
        If e.PropertyName.Equals(NameOf(Me.MyName.Name)) = True Then
            Me.CountOfChanges += 1
        End If
    End Sub
End Class

使用NUnitNSubstitute进行测试 测试更改Name(引发PropertyChanged事件)将更新CountOfChanges proerty

<Test>
Public Sub CountOfChanges_NameChanged_ShouldIncreaseByOne()
  Dim previuosCount As Integer = 0
  Dim nextCount As Integer = previuos + 1
  Dim fakename As ObservableName = Substitute.For(Of ObservableName)()
  Dim vm As New ViewModel(fakename)
  vm.CountOfChanges = previuosCount 

  AddHandler vm.MyName.PropertyChanged, Raise.Event(Of PropertyChangedEventHandler)(vm.MyName, New PropertyChangedEventArgs(NameOf(vm.MyName.Name)))

  Assert.AreEqual(nextCount, vm.CountOfChanges)
End Sub

使用上面的代码永远不会引发PropertyChanged事件,但是直接使用传递INotifyPropertyChanged的下一个测试会成功提升事件

<Test>
Public Sub PropertyChanged_RaiseEvent()
    Dim test As INotifyPropertyChanged = Substitute.For(Of INotifyPropertyChanged)()
    Dim isRaised As Boolean = False
    AddHandler test.PropertyChanged, Sub() isRaised = True

    AddHandler test.PropertyChanged, Raise.Event(Of PropertyChangedEventHandler)(test, New PropertyChangedEventArgs("test"))

    Assert.IsTrue(isRaised)
End Sub

1 个答案:

答案 0 :(得分:2)

你真的需要在这里使用NSubstitute并使用白盒测试吗? 如果您设置纯粹的技术兴趣&#34;除此之外,在测试中设置vm.myName.Name属性会更简单,然后声明vm.CountOfChanges增加了。这将是一个黑盒子&#34;方法,它不依赖于内部实现的细节,因此更加健壮。 它仍然完全测试您的功能,只是省略了实现细节

要了解为什么它不能按预期工作,请考虑以下内容。 NSubstitute使用Castle.DynamicProxy来实现替换 - 使用的机制是继承。 事件是通过使用具有相同签名的私有委托字段实现的语言功能。事件的整个目的是封装委托。 由于委托字段是私有的,因此无法在派生类中访问它,因此无法触发事件。 要在继承的类中引发基类事件,基类必须有一个用于引发事件的vitual方法,继承的类必须覆盖该事件,例如,请参阅this link,但对此有很多很好的解释。幅。