Testing events - traditional method
In order to test that an event has been fired from the tested object, one would typically do something like this:
// Arrange
var testee = new Testee();
bool eventWasFired = false;
testee.MyEvent += (s,e) => eventWasFired = true;
// Act
testee.SomeMethod();
// Assert
Assert.That(eventWasFired, Is.True);
// Arrange
var testee = new Testee();
bool eventWasFired = false;
model.PropertyChanged += (s, e) =>
{
if (e.PropertyName == "SomeProperty")
{
eventWasFired = true;
}
};
// Act
testee.SomeMethod();
// Assert
Assert.That(eventWasFired, Is.True);
This can be tweaked as needed to assert that an event was NOT fired or to assert that the event was fired a given number of times. However, it is not as obvious and readable as one would like. Keep in mind the axe murderer who is going to read your tests!
Having so much more fun with the constraint model
One of the advantages of the NUnit constraint model is the extensibility. My event asserts allows you to test for events like this:
// Arrange
var testee = new Testee();
Listen.To(testee);
// Act
testee.SomeMethod();
// Assert
Assert.That(testee, Did.Fire.TheEvent("SomeEvent"));
I dare to say that this is slightly more readable and less complex than the traditional method! Specifying the event with a string is not typesafe, which is a bit sad. You will not get a compile error if the event does not exist. However, the assert will throw an IllegalArgumentException if the event does not exist. Hence, you will not get false positives or negatives because the event was misspelled.
The difference is even more obvious when testing for a PropertyChangedEvent (compare with the second traditional example):
The other variants can be tested with
I have uploaded the source code with the required constraints here. Simply add them to your test project or a shared test helper project, and you are good to go. Code samples in the form of tests (of course) are included in the DidTest class. The constraint class is doing a lot of safeguarding to prevent the developer from using a wrong syntax.
Have fun!
The difference is even more obvious when testing for a PropertyChangedEvent (compare with the second traditional example):
// Arrange
var testee = new Testee();
Listen.To(testee);
// Act
testee.SomeMethod();
// Assert
Assert.That(testee, Did.Fire.ThePropertyEvent("SomeProperty"));
The other variants can be tested with
Assert.That(testee, Did.Not.Fire.TheEvent("SomeEvent"));
Assert.That(testee, Did.Fire.TheEvent("SomeEvent").Once);
Assert.That(testee, Did.Fire.ThePropertyEvent("SomeProperty").Times(3));
I have uploaded the source code with the required constraints here. Simply add them to your test project or a shared test helper project, and you are good to go. Code samples in the form of tests (of course) are included in the DidTest class. The constraint class is doing a lot of safeguarding to prevent the developer from using a wrong syntax.
Have fun!