CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Patrick Smacchia [MVP C#]


Simplify your unit test code with some C# anonymous methods

While writing some unit test to check that an event was indeed triggered, I figured out that anonymous methods can be a great help to avoid writing some mock handler methods.

Here is the case. I have a class Foo that implements the System.ComponentModel.INotifyPropertyChanged interface. This interface has just one event, PropertyChanged, that will let its handlers know about the name of the property of Foo that have changed. Basically, my unit test looks like:

 

[Test]

public void Test_ModifyReport_NotifyPropertyChanged() {

   int nbProp1Changed = 0;

   int nbProp2Changed = 0;

   // ...

 

   Foo foo = new Foo();

 

   foo.PropertyChanged +=

      delegate(object sender,

               PropertyChangedEventArgs propertyChangedEventArgs) {

      Debug.Assert(sender == project);

      switch (propertyChangedEventArgs.PropertyName) {

         case Constants.PROPERTY1_NAME:

            nbProp1Changed ++; return;

         case Constants.PROPERTY2_NAME:

            nbProp2Changed ++; return;

         // ...

      }

   };

 

   Assert.IsTrue(Foo.Prop1 != 3);

   Assert.IsTrue(nbProp1Changed == 0);

   Foo.Prop1 = 3;

   Assert.IsTrue(nbProp1Changed == 1);

 

   // Test PropertyChanged not triggered when the value is the same

   Foo.Prop1 = 3;

   Assert.IsTrue(nbProp1Changed == 1);

   //…

}

Of course, if you have a large number of properties, you could create a dictionary of ‘Number of times the property X has been changed’ indexed by ‘The property X name’.

The beauty of this trick is that it avoids creating some handlers method and corresponding field state to check that an event is triggered. Actually, this code is much more tricky than it looks like at first glance. Under the hood, the C# compiler is creating a dedicated class to hold the nbXXXChanged value (see with Reflector).  We say that the states nbXXXChanged have been captured by the anonymous method. We are then talking with a functional programming vocabulary because in fact we created what is named a closure in the functional world.

I won’t go into the details of anonymous method compilation and closure because I described all this in an article published on TSS.NET 3 years ago (read it here). You can also read the second part of the article about the yield keyword here.



About Patrick Smacchia

Patrick Smacchia is a Visual C# MVP involved in software development for over 15 years. After graduating in mathematics and computer science, he has worked on software in a variety of fields including stock exchange, airline ticket reservation system as well as a satellite base station at Alcatel. He's currently a software consultant and trainer on .NET technologies as well as the lead developer of the tool NDepend which provides numerous metrics and caveats on any compiled .NET application. He is the author of Practical .NET2 and C#2, a .NET book conceived from real world experience with 647 compilable code listings. Check out Devlicio.us!