Skip to main content

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 sut = new MyClass();

// ↓ Records all events
IEventRecording<MyClass> recording = sut.Record().Events();
IEventRecording<MyClass> recording = sut.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 = sut.Record().Events();

// Perform some action on the subject under test
sut.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 = sut.Record().Events();

sut.OnThresholdReached(new ThresholdReachedEventArgs(5));
sut.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 = sut.Record().Events();

_ = Task.Delay(2.Seconds()).ContinueWith(_ => {
// Trigger the events in the background
sut.OnThresholdReached(new ThresholdReachedEventArgs(5));
sut.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 = sut.Record().Events();

sut.OnThresholdReached(new ThresholdReachedEventArgs(5));

await Expect.That(recording).Triggered(nameof(MyClass.ThresholdReached))
.WithSender(s => s == sut);

EventArgs

When you follow the event best practices, you can filter the recorded events based on their EventArgs (the second parameter):

IEventRecording<MyClass> recording = sut.Record().Events();

sut.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 = sut.Record().Events();

sut.OnThresholdReached(new ThresholdReachedEventArgs(5));
sut.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 sut = // ...implements INotifyPropertyChanged
IEventRecording<MyClass> recording = sut.Record().Events();

// do something that triggers the PropertyChanged event
sut.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");