BlackWaspTM
Testing
.NET 1.1+

Unit Testing Raised Events

Many classes use events to allow messages to be passed to other classes in a loosely coupled manner. When creating unit tests for classes that use events, the raising of those events and the arguments generated should be verified.

Testing Events

When you are developing an application that uses events to pass messages between classes, you should unit test the events to ensure correct operation. This includes testing that a class that raises events does so as expected. It also means testing that consumers of events correctly identify that an event has been raised and react accordingly. In this article we will look at the former. A later article will discuss how you can test the reaction to events raised by dependencies.

When testing that a class raises events correctly, there are three elements to verify. Firstly, the class should raise the correct event according to the process being executed. Secondly, the event should refer to the object that raised it. Finally, any event arguments pertinent to the event should be set to the expected values. We can test all three of these items using NUnit. We will see examples using code suitable for .NET 1.1, 2.0 and 3.5, though these methods are compatible with other versions.

Code Under Test

In order to demonstrate the testing of events, we need a sample class. The Car class, shown below, is a variation upon the example in the C# Events article. It represents a car that has a speed and can accelerate. When accelerating to above the safe speed limit, an event is raised:

public class Car
{
    private int _speed = 0;
    private int _safetySpeed = 70;

    public event SpeedLimitExceededEventHandler SpeedLimitExceeded;

    public int Speed
    {
        get { return _speed; }
        set { _speed = value; }
    }

    public void Accelerate(int mph)
    {
        int oldSpeed = _speed;
        _speed += mph;

        if (oldSpeed <= _safetySpeed && _speed > _safetySpeed)
        {
            SpeedEventArgs e = new SpeedEventArgs();
            e.ExcessSpeed = _speed - _safetySpeed;
            OnSpeedLimitExceeded(e);
        }
    }

    private void OnSpeedLimitExceeded(SpeedEventArgs e)
    {
        if (SpeedLimitExceeded != null) SpeedLimitExceeded(this, e);
    }
}

The SpeedLimitExceeded event is based upon the SpeedLimitExceededEventHandler delegate. To define this delegate, add the following line of code to the namespace, outside of the class' code block.

public delegate void SpeedLimitExceededEventHandler(object source, SpeedEventArgs e);

Finally, we need to create a class for the event arguments. The SpeedEventArgs type includes a single property, which contains the excess speed of the car.

public class SpeedEventArgs : EventArgs
{
    private int _excessSpeed;

    public int ExcessSpeed
    {
        get { return _excessSpeed; }
        set { _excessSpeed = value; }
    }
}
15 June 2011