NSubstitute vs PRISM EventAggregator: Assert that calling a method triggers event with correct payload

倾然丶 夕夏残阳落幕 提交于 2019-11-30 09:24:45

问题


Consider the below method that updates a person and publishes an event through the PRISM EventAggregator to indicate that the person has been updated.

I would like to unit test that the message is sent with the correct payload. In this case that would mean the correct 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
            };
        });
}

I know that I can create a substitute for the event aggregator:

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

However, I don't know how to detect when a message is sent and how to check its payload.


回答1:


I'm not an experienced unit tester so I'm not sure this is the correct unit test to write. But anyway, this is how I tested it so far and it seems to do what I want.

[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);
}

Feedback welcome.




回答2:


You can actually substitute away the event aggregator like this:

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;
        }
    }
}

Note the fake event class that's foisted on the subject under test to get access to the payload.




回答3:


Just add a subscriber to your unit test and check the result of the delegate. See Prism's IEventAggregator unit tests as an example

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



来源:https://stackoverflow.com/questions/35868184/nsubstitute-vs-prism-eventaggregator-assert-that-calling-a-method-triggers-even

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!