Events
Describes the possible expectations for verifying events.
Recording
First, you have to start a recording of events. This can be done with the .Record().Events() extension method in the "
aweXpect.Recording" namespace.
class ThresholdReachedEventArgs(int threshold = 0) : EventArgs
{
public int Threshold { get; } = threshold;
}
class MyClass
{
public event EventHandler? ThresholdReached;
public void OnThresholdReached(ThresholdReachedEventArgs e)
=> ThresholdReached?.Invoke(this, e);
}
MyClass subject = new MyClass();
// ↓ Records all events
IEventRecording<MyClass> recording = subject.Record().Events();
IEventRecording<MyClass> recording = subject.Record().Events(nameof(MyClass.ThresholdReached));
// ↑ Records only the ThresholdReached event
Triggering
You can verify that a recording recorded an event:
// Start the recording
IEventRecording<MyClass> recording = subject.Record().Events();
// Perform some action on the subject under test
subject.OnThresholdReached(new ThresholdReachedEventArgs());
// Expect that the ThresholdReached event was triggered at least once
await Expect.That(recording).Triggered(nameof(MyClass.ThresholdReached));
Filtering
You can filter the recorded events based on their parameters.
IEventRecording<MyClass> recording = subject.Record().Events();
subject.OnThresholdReached(new ThresholdReachedEventArgs(5));
subject.OnThresholdReached(new ThresholdReachedEventArgs(15));
await Expect.That(recording).Triggered(nameof(MyClass.ThresholdReached))
.WithParameter<ThresholdReachedEventArgs>(e => e.Threshold > 10);
Timeout
You can specify a timeout within the expected events should be triggered:
IEventRecording<MyClass> recording = subject.Record().Events();
_ = Task.Delay(2.Seconds()).ContinueWith(_ => {
// Trigger the events in the background
subject.OnThresholdReached(new ThresholdReachedEventArgs(5));
subject.OnThresholdReached(new ThresholdReachedEventArgs(15));
});
await Expect.That(recording).Triggered(nameof(MyClass.ThresholdReached))
.WithParameter<ThresholdReachedEventArgs>(e => e.Threshold > 10)
.Within(3.Seconds());
The .Within(TimeSpan) method will wait up to 3 seconds for the expected events and
finish successfully as soon as the events are triggered.
Sender
When you follow the event best practices, you can filter the recorded events based on the sender (the first parameter):
IEventRecording<MyClass> recording = subject.Record().Events();
subject.OnThresholdReached(new ThresholdReachedEventArgs(5));
await Expect.That(recording).Triggered(nameof(MyClass.ThresholdReached))
.WithSender(s => s == subject);
EventArgs
When you follow
the event best practices,
you can filter the recorded events based on their EventArgs (the second parameter):
IEventRecording<MyClass> recording = subject.Record().Events();
subject.OnThresholdReached(new ThresholdReachedEventArgs(5));
await Expect.That(recording).Triggered(nameof(MyClass.ThresholdReached))
.With<ThresholdReachedEventArgs>(e => e < 10);
Counting
You can verify that an event was recorded a specific number of times
IEventRecording<MyClass> recording = subject.Record().Events();
subject.OnThresholdReached(new ThresholdReachedEventArgs(5));
subject.OnThresholdReached(new ThresholdReachedEventArgs(15));
await Expect.That(recording).Triggered(nameof(MyClass.ThresholdReached))
.Between(1).And(2.Times();
You can use the same occurrence constraints as in the contain method:
AtLeast(2.Times())AtMost(3.Times())Between(1).And(4.Times())Exactly(0.Times())
Special events
For common events, you can create specific overloads.
Included are some overloads for the
INotifyPropertyChanged.PropertyChanged
event:
MyClass subject = // ...implements INotifyPropertyChanged
IEventRecording<MyClass> recording = subject.Record().Events();
// do something that triggers the PropertyChanged event
subject.Execute();
await Expect.That(recording).TriggeredPropertyChanged()
.Because("it should trigger the PropertyChanged event for any property name");
await Expect.That(recording).TriggeredPropertyChangedFor(x => x.MyProperty)
.Because("it should trigger the PropertyChanged event for the 'MyProperty' property name");
await Expect.That(recording).DidNotTriggerPropertyChanged()
.Because("it should not trigger for any property name");
await Expect.That(recording).DidNotTriggerPropertyChangedFor(x => x.MyProperty)
.Because("it should not trigger for the 'MyProperty' property name");