NSubstitute vs PRISM EventAggregator:断言调用方法会触发具有正确负载的事件
NSubstitute vs PRISM EventAggregator: Assert that calling a method triggers event with correct payload
考虑以下更新人员并通过 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;
}
}
}
注意假事件 class 强加给被测对象以获取有效负载的访问权限。
只需将订阅者添加到您的单元测试并检查委托的结果。以 Prism 的 IEventAggregator 单元测试为例
在我看来,使用真正的 EventAggregator 而不是模拟会使测试更易于编写和阅读。
但是,我偶然发现了一个问题,如果它们是 运行 作为测试套件的一部分,我的测试有时会失败:
从测试代码订阅事件时(断言被测代码正确发布了事件),需要向订阅方法提供以下附加参数:
event.Subscribe(...,
threadOption: ThreadOption.PublisherThread,
keepSubscriberReferenceAlive: true)
不然测试订阅有时触发不了
Prism 的作者在他们自己的测试中这样做 (https://github.com/PrismLibrary/Prism/blob/master/tests/Prism.Core.Tests/Events/PubSubEventFixture.cs)
考虑以下更新人员并通过 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;
}
}
}
注意假事件 class 强加给被测对象以获取有效负载的访问权限。
只需将订阅者添加到您的单元测试并检查委托的结果。以 Prism 的 IEventAggregator 单元测试为例
在我看来,使用真正的 EventAggregator 而不是模拟会使测试更易于编写和阅读。 但是,我偶然发现了一个问题,如果它们是 运行 作为测试套件的一部分,我的测试有时会失败:
从测试代码订阅事件时(断言被测代码正确发布了事件),需要向订阅方法提供以下附加参数:
event.Subscribe(...,
threadOption: ThreadOption.PublisherThread,
keepSubscriberReferenceAlive: true)
不然测试订阅有时触发不了
Prism 的作者在他们自己的测试中这样做 (https://github.com/PrismLibrary/Prism/blob/master/tests/Prism.Core.Tests/Events/PubSubEventFixture.cs)