Unit-testing Synchronous Events

It’s easy to forget (or choose not to) test events when you’re writing test-driven code, but they mustn’t be ignored because client code which subscribes to your events will depend on them firing under the correct circumstances. And without tests to prove this happens, there is no guarantee that they are doing their job properly, which will have a serious impact on all of the subscribers.

What might deter developers is the pub/sub nature of events, but this is no barrier to testing their behaviour. Assuming the event is triggered by a call to a synchronous method, then the result will be a call by the same thread (therefore on the same call stack) to one or more event handler delegates – so there are no asynchronous timing or thread issues to be worry about. Handling asynchronous events is slightly more difficult which I discuss at the bottom of this article.

Example
Here is an example based on a retail website’s shopping basket (cart) which fires an event whenever an item is added or removed from the basket. To start with, here’s an NUnit test to check that an event fires whenever an item is added to the basket. It requires a field to tell us if the event has fired, and an event handler which sets the field to true. The event handler basket_ItemCountChanged is then hooked up to the ItemCountChanged event.

The test currently doesn’t compile because the types/methods/properties marked in red don’t exist yet, so here is the code to make it pass. There is a simple product interface and concrete class which is what gets added to the basket.

And here is the shopping basket itself.  It’s generic so that it can store any type, has an internal collection of items of type T, and fires the ItemCountChanged event whenever an item is added to the basket. Note: to keep the example simple, I have excluded code to make shared data access thread-safe.

Refactoring the test
The test now passes, however it’s a bit messy. So we can simplify it by dispensing with the _eventFired field and basket_ItemCountChanged event handler and replacing them with a local variable and an anonymous delegate in the form of a simple lambda expression. Not only does this make the test completely self-contained, but it’s a lot neater and more readable now.

Finally, re-run the test which goes green.

In the next post I discuss testing asynchronous events.

Advertisements

About Phil Munro

I have been developing commercial desktop and distributed web applications with Microsoft technologies since 1997.
This entry was posted in C#, NUnit, TDD. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s