- Getting started
- Creating a substitute
- Setting a return value
- Return for specific args
- Return for any args
- Return from a function
- Multiple return values
- Replacing return values
- Checking received calls
- Clearing received calls
- Argument matchers
- Callbacks, void calls and When..Do
- Throwing exceptions
- Safe configuration and overlapping calls
- Raising events
- Auto and recursive mocks
- Setting out and ref args
- Actions with argument matchers
- Checking call order
- Partial subs and test spies
- Return for all calls of a type
- Threading
- Compatibility argument matchers
- NSubstitute.Analyzers
- How NSubstitute works
- Search
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);