NSubstitute vs PRISM 事件聚合器:断言调用方法会触发具有正确有效负载的事件



请考虑以下方法,该方法更新人员并通过PRISM EventAggregator发布事件以指示此人已更新。

我想对消息是否以正确的有效负载发送进行单元测试。在这种情况下,这意味着正确的 personId。

public void UpdatePerson(int personId)
{
    // Do whatever it takes to update the person
    // ...
    // Publish a message indicating that the person has been updated
    _eventAggregator
        .GetEvent<PersonUpdatedEvent>()
        .Publish(new PersonUpdatedEventArgs
        {
            Info = new PersonInfo
            {
                Id = personId,
                UpdatedAt = DateTime.Now
            };
        });
}

我知道我可以创建事件聚合器的替代品:

var _eventAggregator = Substitute.For<IEventAggregator>();

但是,我不知道如何检测何时发送消息以及如何检查其有效负载。

我不是一个有经验的单元测试人员,所以我不确定这是正确的单元测试。但无论如何,这就是我到目前为止测试它的方式,它似乎做了我想做的事。

[Test]
public void TestPersonUpdateSendsEventWithCorrectPayload()
{
    // ARRANGE
    PersonUpdatedEventArgs payload = null;
    _eventAggregator
        .GetEvent<PersonUpdatedEvent>()
        .Subscribe(message => payload = message);
    // ACT
    _personService.UpdatePerson(5);
    // ASSERT
    payload.Should().NotBeNull();
    payload.Id.Should().Be(5);
}

欢迎反馈。

您实际上可以像这样替换事件聚合器:

public class ToBeTested
{
    private readonly IEventAggregator _eventAggregator;
    public ToBeTested( IEventAggregator eventAggregator )
    {
        _eventAggregator = eventAggregator;
    }
    public void DoStuff()
    {
        _eventAggregator.GetEvent<OneEvent>().Publish( "test" );
    }
}
public class OneEvent : PubSubEvent<string>
{
}
[TestFixture]
internal class Test
{
    [Test]
    public void DoStuffTest()
    {
        var myEvent = new MyOneEvent();
        var myEventAggregator = Substitute.For<IEventAggregator>();
        myEventAggregator.GetEvent<OneEvent>().Returns( myEvent );
        var toBeTested = new ToBeTested( myEventAggregator );
        toBeTested.DoStuff();
        Assert.That( myEvent.ReceivedPayload, Is.EqualTo( "test" ) );
    }
    private class MyOneEvent : OneEvent
    {
        public override void Publish( string payload )
        {
            ReceivedPayload = payload;
        }
        public string ReceivedPayload
        {
            get;
            private set;
        }
    }
}

请注意强加给受测主体的假事件类,以获取对有效负载的访问权限。

只需将订阅者添加到单元测试并检查委托的结果即可。 请参阅 Prism 的 IEventAggregator 单元测试作为示例

https://github.com/PrismLibrary/Prism/blob/master/Source/Prism.Tests/Events/PubSubEventFixture.cs#L14

在我看来,使用真正的 EventAggregator 而不是模拟使测试更容易编写和阅读。但是,我偶然发现了一个问题,即如果作为测试套件的一部分运行,我的测试有时会失败:

从测试代码订阅事件时(以断言受测代码正确发布了事件),需要向 Subscribe 方法提供以下附加参数:

event.Subscribe(..., 
                threadOption: ThreadOption.PublisherThread, 
                keepSubscriberReferenceAlive: true)

否则,有时不会触发测试订阅。

棱镜的作者在他们自己的测试中这样做(https://github.com/PrismLibrary/Prism/blob/master/tests/Prism.Core.Tests/Events/PubSubEventFixture.cs)

最新更新