Testing Events Using Anonymous Methods

If you are unit testing a class which may raise an event, it will be appropriate to test that the event is raised when appropriate. Before .NET 2.0, you had to attach an event handler to an instance of the class to test the event, but now you can do it with anonymous methods.

This is probably best illustrated by an example. Imagine that you are developing the following class:

 public class MyEventRaiser
 {
     public event EventHandler MyEvent;
  
     public void Raise()
     {
         if (this.MyEvent != null)
         {
             this.MyEvent(this, EventArgs.Empty);
         }
     }
 }

You must excuse the simplicity of the example; the only thing this class really does is raise an event.

In .NET 1.1, the best way you could test if the event was actually raised was like this:

 private bool eventWasRaised_;
  
 [TestMethod]
 public void WithoutAnonymousMethod()
 {
     this.eventWasRaised_ = false;
  
     MyEventRaiser eventRaiser = new MyEventRaiser();
     eventRaiser.MyEvent += 
         new EventHandler(eventRaiser_MyEvent);
  
     eventRaiser.Raise();
  
     Assert.IsTrue(this.eventWasRaised_);
 }
  
 private void eventRaiser_MyEvent(object sender, EventArgs e)
 {
     this.eventWasRaised_ = true;
 }

As you can tell, it's necessary to create three members of the unit test class to perform a single test:

  • A private member variable to track whether the event was raised.
  • The test method itself.
  • An event handler method.

Personally, I feel that each unit test should be completely contained within its own test method if at all possible, and testing events like this violates that principle. In my simple example, this doesn't seem so bad, but as you write more tests, things get more complicated: You need to reset all your member variables for each test, since tests should be indpendent, etc.

Luckily, .NET 2.0 includes support for anonymous methods, so you can now rewrite the test:

 [TestMethod]
 public void WithAnonymousMethod()
 {
     bool eventWasRaised = false;
  
     MyEventRaiser eventRaiser = new MyEventRaiser();
     eventRaiser.MyEvent += 
         delegate(object sender, EventArgs e) {
             eventWasRaised = true;
         };
  
     eventRaiser.Raise();
  
     Assert.IsTrue(eventWasRaised);
 }

This is much simpler, and follows the principle that each unit test should be self-contained. There are no member variables or external event handler methods involved. The code is more compact, and I find it more readable, too. You can even do Asserts in the anonymous method, if you need to validate the EventArgs, etc.