Reputation: 3278
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?
Upvotes: 1
Views: 339
Reputation: 868
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);
}
Upvotes: 1
Reputation: 42245
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.
Upvotes: 7