[英]How do I unit test the event raised by class under test?
我有下面的 class 负责根据某些业务条件引发事件。
public class EventRaiserClass : IEventRaiserClass
{
public event EventHandler SendEventToClient;
public void RaiseEventForClient()
{
SendEventToClient?.Invoke(this, EventArgs.Empty);
}
}
这是我的客户 class
public class Client :IClient
{
EventRaiserClass _eventRaiser;
public Client(EventRaiserClass eventraiser)
{
_eventRaise = eventraise;
_iotGwStatus.SendEventToClient += OnSendEventToClient;
}
private async void OnSendEventToClient(object sender, EventArgs e)
{
await SendEventToClient();
}
public async Task SendEventToClient()
{
//do some operation
}
}
EventRaiserClass
被注入到class下面,负责处理一些订单
public class ProcessRequest: IProcessRequest
{
IEventRaiserClass _evntRaiser;
public ProcessRequest(IEventRaiserClass evntRaiser)
{
_evntRaiser = evntRaiser;
}
public void Process(JObject json)
{
_evntRaiser.RaiseEventForClient();
}
}
现在,我如何对上述Process
方法进行单元测试? 如何确保在调用process
方法时引发事件?
据我所知, Client
class 与这个问题无关? 您只想测试调用ProcessRequest.Process
调用EventRaiserClass.RaiseEventForClient
。
使用EventRaiserClass
的简单方法,无需任何模拟:
var eventRaiser = new EventRaiserClass();
bool eventRaised = false;
eventRaiser.SendEventToClient += (o, e) => eventRaised = true;
var processRequest = new ProcessRequest(eventRaiser);
processRequest.Process(someJObject);
Assert.True(eventRaised);
您可以进一步 go 并测试事件是否仅引发一次:
// Arrange
var eventRaiser = new EventRaiserClass();
int eventRaisedCount = 0;
eventRaiser.SendEventToClient += (o, e) => eventRaisedCount++;
var processRequest = new ProcessRequest(eventRaiser);
// Act
processRequest.Process(someJObject);
// Assert
Assert.Equal(1, eventRaisedCount);
如果您不想依赖EventRaiserClass
并且您正在使用 mocking 框架,您可以执行以下操作(我在此示例中使用Moq ):
// Arrange
var eventRaiser = Mock<IEventRaiser>();
var processRequest = new ProcessRequest(eventRaiser.Object);
// Act
processRequest.Process(someJObject);
// Assert
eventRaiser.Verify(x => x.RaiseEventForClient());
同样使用NSubstitute :
// Arrange
var eventRaiser = Substitute.For<IEventRaiser>();
var processRequest = new ProcessRequest(eventRaiser);
// Act
processRequest.Process(someJObject);
// Assert
eventRaiser.Received().RaiseEventForClient();
作为单独的说明,请考虑一下如何命名类。 大多数编码标准都规定类应该使用名词或名词短语来命名,并且不应以“类”结尾。
所以Client
没问题,但是EventRaiserClass
以Class
。 考虑类似EventRaiser
的东西。
ProcessRequest
不是名词或名词短语——它听起来像一个指令(“处理此请求”),这通常是您命名方法的方式,而不是 class。 考虑类似RequestProcessor
的东西,它是一个处理请求的 object。
您可能还想检查有关sender和eventArgs的抛出事件。 如果您不想编写三个测试方法来测试整个事件引发过程,那么Nuclear.Test适合您。
[TestMethod]
void TestProcessRaisesEvent() {
// arrange
var eventRaiser = new EventRaiserClass();
var processRequest = new ProcessRequest(eventRaiser);
var json = default(JObject); // create your json
Action action = () => processRequest.Process(json);
// act / assert
Test.If.RaisesEvent(eventRaiser, "SendEventToClient", action, out Object sender, out EventArgs e);
Test.If.ReferencesEqual(eventRaiser, sender);
Test.If.ValuesEqual(e, EventArgs.Empty);
}
但是,您应该考虑分别测试EventRaiserClass
和ProcessRequest
。
[TestMethod]
void TestEventRaiserRaisesEvent() {
// arrange
var eventRaiser = new EventRaiserClass();
Action action = () => eventRaiser.RaiseEventForClient();
// act / assert
Test.If.RaisesEvent(eventRaiser, "SendEventToClient", action, out Object sender, out EventArgs e);
Test.If.ReferencesEqual(eventRaiser, sender);
Test.If.ValuesEqual(e, EventArgs.Empty);
}
[TestMethod]
void TestProcessRaisesEvent() {
// arrange
var eventRaiser = new EventRaiserClass();
var processRequest = new ProcessRequest(eventRaiser);
var json = default(JObject); // create your json
Action action = () => processRequest.Process(json);
// act / assert
Test.If.RaisesEvent(eventRaiser, "SendEventToClient", action, out Object sender, out EventArgs e);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.