Raising events

Sometimes it is necessary to raise events declared on the types being substituted for. Consider the following example:


public interface IEngine {
    event EventHandler Idling;
    event EventHandler<LowFuelWarningEventArgs> LowFuelWarning;
    event Action<int> RevvedAt;
}

public class LowFuelWarningEventArgs : EventArgs {
    public int PercentLeft { get; private set; }
    public LowFuelWarningEventArgs(int percentLeft) {
        PercentLeft = percentLeft;
    }
}

Events are “interesting” creatures in the .NET world, as you can’t pass around references to them like you can with other members. Instead, you can only add or remove handlers to events, and it is this add handler syntax that NSubstitute uses to raise events.

var wasCalled = false;
engine.Idling += (sender, args) => wasCalled = true;

//Tell the substitute to raise the event with a sender and EventArgs:
engine.Idling += Raise.EventWith(new object(), new EventArgs());

Assert.True(wasCalled);

In the example above we don’t really mind what sender and EventArgs our event is raised with, just that it was called. In this case NSubstitute can make our life easier by creating the required arguments for our event handler:

engine.Idling += Raise.Event();
Assert.True(wasCalled);

Raising events when arguments do not have a default constructor

NSubstitute will not always be able to create the event arguments for you. If your event args do not have a default constructor you will have to provide them yourself using Raise.EventWith<TEventArgs>(...), as is the case for the LowFuelWarning event. NSubstitute will still create the sender for you if you don’t provide it though.

engine.LowFuelWarning += (sender, args) => numberOfEvents++;

//Raise event with specific args, any sender:
engine.LowFuelWarning += Raise.EventWith(new LowFuelWarningEventArgs(10));
//Raise event with specific args and sender:
engine.LowFuelWarning += Raise.EventWith(new object(), new LowFuelWarningEventArgs(10));

Assert.AreEqual(2, numberOfEvents);

Raising Delegate events

Sometimes events are declared with a delegate that does not inherit from EventHandler<T> or EventHandler. These events can be raised using Raise.Event<TypeOfEventHandlerDelegate>(arguments). NSubsitute will try and guess the arguments required for the delegate, but if it can’t it will tell you what arguments you need to supply.

The following examples shows raising an INotifyPropertyChanged event, which uses a PropertyChangedEventHandler delegate and requires two parameters.

var sub = Substitute.For<INotifyPropertyChanged>();
bool wasCalled = false;
sub.PropertyChanged += (sender, args) => wasCalled = true;

sub.PropertyChanged += Raise.Event<PropertyChangedEventHandler>(this, new PropertyChangedEventArgs("test"));

Assert.That(wasCalled);

Raising Action events

In the IEngine example the RevvedAt event is declared as an Action<int>. This is another example of a delegate event, and we can use Raise.Event<Action<int>>() to raise our event.

int revvedAt = 0;;
engine.RevvedAt += rpm => revvedAt = rpm;

engine.RevvedAt += Raise.Event<Action<int>>(123);

Assert.AreEqual(123, revvedAt);