I have below class which is responsible for raising the event based on some business conditions.
public class EventRaiserClass : IEventRaiserClass
{
public event EventHandler SendEventToClient;
public void RaiseEventForClient()
{
SendEventToClient?.Invoke(this, EventArgs.Empty);
}
}
Here is my Client 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
is injected to below class which is responsible for processing some orders
public class ProcessRequest: IProcessRequest
{
IEventRaiserClass _evntRaiser;
public ProcessRequest(IEventRaiserClass evntRaiser)
{
_evntRaiser = evntRaiser;
}
public void Process(JObject json)
{
_evntRaiser.RaiseEventForClient();
}
}
Now, How do I unit test above Process
method? How do I make sure the event is raised when process
method is called?
As far as I can tell, the Client
class is irrelevant to this question? You just want to test the calling ProcessRequest.Process
calls EventRaiserClass.RaiseEventForClient
.
A simple way, without any mocks, using the 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);
You can go further, and test that the event is raised exactly once:
// 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);
If you don't want to rely on EventRaiserClass
and you're using a mocking framework, you can do something like this (I'm using Moq in this example):
// Arrange
var eventRaiser = Mock<IEventRaiser>();
var processRequest = new ProcessRequest(eventRaiser.Object);
// Act
processRequest.Process(someJObject);
// Assert
eventRaiser.Verify(x => x.RaiseEventForClient());
The same using NSubstitute :
// Arrange
var eventRaiser = Substitute.For<IEventRaiser>();
var processRequest = new ProcessRequest(eventRaiser);
// Act
processRequest.Process(someJObject);
// Assert
eventRaiser.Received().RaiseEventForClient();
As a separate note, think a bit about how you name your classes. Most coding standards say that classes should be named using a noun or noun phrase , and shouldn't end with "Class".
So Client
is OK, but EventRaiserClass
ends with Class
. Consider something like EventRaiser
.
ProcessRequest
isn't a noun or noun phrase -- it sounds like an instruction ("process this request"), which is typically how you'd name a method, not a class. Consider something like RequestProcessor
, which is an object which processes requests.
You may also want to check the thrown event with regard to sender and eventArgs . If you don't want to write three test methods to test the entire event raising procedure, then Nuclear.Test is for you.
[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);
}
You should consider testing EventRaiserClass
and ProcessRequest
separately however.
[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);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.