Events are critical for any software application because they help to decouple and improve the extensibility of the software system. Therefore, unit testing the code that raises an event is a must to ensure its correct operation and that the system reacts according to how it should.
This article explains how to unit test code that raises an event in C#. You will also see an example of how to use Moq, a mocking framework, to raise an event in your test methods.
How to unit test that events are raised in C#?
Application code that consists of events enables a class or object to notify other classes that a particular event has occurred. When writing unit tests for such code, raised events and arguments must be tested. In C#, you can use any unit testing framework to test code that raises events.
Let’s go over a simple example to see how to unit test such code.
This example program gets a set of input numbers, adds those numbers together, and checks if the total value exceeds a specific threshold value or the maximum total value specified by the user. If the program exceeds the threshold value, the program raises the event OnThresholdExceeded
.
If the program works as expected, it must raise this event for every total value that exceeds the threshold value.
public class EventExample
{
public int totalValue;
public int thresholdValue;
public EventExample(int userDefinedThreshold)
{
thresholdValue = userDefinedThreshold;
}
public void AddToCounter(int x)
{
totalValue += x;
// check if the threshold is exceeded.
if (totalValue > thresholdValue)
{
var eventArgs = new ThresholdExceededEventArgs();
eventArgs.Threshold = thresholdValue;
OnThresholdExceeded(eventArgs);
}
}
//event raised when the total value exceeds the threshold
public void OnThresholdExceeded(ThresholdExceededEventArgs e)
{
ThresholdExceededEventHandler eventHandler = ThresholdExceeded;
if (eventHandler != null)
{
eventHandler(this, e);
}
}
//The event handler object
public event ThresholdExceededEventHandler ThresholdExceeded;
}
The following code sets the event handler’s arguments and uses a delegate to set the event handler.
public class ThresholdExceededEventArgs : EventArgs
{
public int Threshold { get; set; }
}
public delegate void ThresholdExceededEventHandler(Object sender, ThresholdExceededEventArgs e);
So how do you test this code to check if it raises the events correctly?
First, create a separate unit test project and add a reference to the project with the code you will write the unit test.
Then, inside the test method, create an event class object and initialize the threshold value. After that, input values to the method AddToCounter
that is greater than the defined threshold. Check if the program triggers the OnThresholdExceeded
event using the event handler ThresholdExceeded
correctly whenever the input value causes the total value to go beyond the threshold.
Finally, use an assertion to check if the expected total value that should raise an event equals the actual total value that raised it. You can check this for different threshold values and confirms that the code works as expected.
[Fact]
public void Exceeding_threshold_raises_an_event()
{
int userDefinedThreshold = 20;
EventExample obj = new EventExample(userDefinedThreshold);
int expectedTotalThatExceedThreshold = userDefinedThreshold;
int actualTotalThatExceedThreshold = 0;
obj.ThresholdExceeded += delegate (object sender, ThresholdExceededEventArgs e)
{
actualTotalThatExceedThreshold = e.Threshold;
};
obj.AddToCounter(21);
Assert.Equal(userDefinedThreshold, actualTotalThatExceedThreshold);
}
As you can see, the program successfully raises the events whenever the total value exceeds 20.
How to raise the event with Moq?
Writing unit tests for events in real-world applications can be tedious, especially when you have a larger codebase with many different event scenarios.
In such cases, you can use Moq, a mocking framework for easily creating unit tests that raise events. It will create mock objects and easily raise events.
Let’s use a simple code example to understand better how to raise events using the Moq framework.
The following program consists of a simple interface class with an event handler that takes two arguments.
public delegate void ExampleEventHandler(int i, bool b);
public interface IExample
{
event ExampleEventHandler exampleEvent;
}
public class ExampleEventArgs : EventArgs
{
public ExampleEventArgs(String value)
{
Value = value;
}
public String Value { get; private set; }
}
Now lets’ see how you can use Moq to raise events.
First, Create a test method. Inside it, create a Mock object from the IExample interface.
var mock = new Mock<IExample>();
Following is how you can use Moq to raise events on the mock object you have created.
mock.Raise(ex => ex.exampleEvent += null, 11, true);
You can also pass event arguments when raising the event as follows.
mock.Raise(m => m.exampleEvent += null, new ExampleEventArgs("test"));
The following code snippet contains the full test class for this example.
public class UnitTestEventWasRaised
{
public void test_where_event_is_raised_with_moq()
{
var mock = new Mock<IExample>();
// Example 1 - Raise the event using the mock object
mock.Raise(ex => ex.exampleEvent += null, 11, true);
// Example 2 - Raise the event using the mock object
// by passing event arguments
mock.Raise(m => m.exampleEvent += null, new ExampleEventArgs("test"));
}
}
As you can see from the above code, the Moq framework provides different ways to raise events so you can check that the program behaves as expected. Apart from raising events, you can do many more things using the Moq framework, such as callbacks, verifications, etc.
Conclusion
Unit testing code that raises an event is a must to ensure its correct operation and that the system reacts according to how it should. This article explained how to unit test code that raises an event in C#.
You have also seen an example of using Moq, a mocking framework, to raise an event in your test methods.