Home > C#, Testing > Generic Extension Methods to Test INotifyPropertyChanged

Generic Extension Methods to Test INotifyPropertyChanged

November 22nd, 2008

Just two extension methods I wrote in order to simplify testing of classes that implement INotifyPropertyChanged.

The first one just checks that the PropertyChanged event fires once and for the specified property:

 
/// <summary>
/// Checks whether a given action produces a change event for
/// a given property.
/// </summary>
/// <typeparam name="T">A class that implements <see cref="INotifyPropertyChanged"/>.
/// </typeparam>
/// <param name="host">The object that contains the changed property.</param>
/// <param name="changeAction">An action that triggers the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
/// <param name="propertyName">The name of the changed property, as advertised by the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
public static void AssertFiresPropertyChangedEvent<T> (this T host, string propertyName,
                                                       Action<T> changeAction)
                                                       where T : INotifyPropertyChanged
{
  bool fired = false;
  
  //register handler with assertion
  PropertyChangedEventHandler handler = (sender, e) =>
    {
      fired = true;
      Assert.AreEqual(propertyName, e.PropertyName);
    };

  //register listener, trigger action, then deregister
  host.PropertyChanged += handler;
  changeAction(host);
  host.PropertyChanged -= handler;

  Assert.IsTrue(fired);
}
 
Now in order to run my test, I can write something like this as long as I’m not having multiple threads that change my object under test:
 
 
//create new user
User user = new User("Tim");

//make sure changing the name raises event
user.AssertFiresPropertyChangedEvent("Name", u => u.Name = "Tom");

 

The second extension method makes sure the event is fired a given number of times for a specified property. Apart from the obvious one (looping a few times), this one has additional use cases:

  • I can test that the event doesn’t fire at all by setting the expected number of events to 0.
  • This method ignores events for other properties, whereas the snippet above fails.

 

/// <summary>
/// Checks whether a given action produces a specified number of property
/// change events for a given property.<br/>
/// This event listener just ignores event for properties other than
/// <paramref name="propertyName"/>.
/// </summary>
/// <typeparam name="T">A class that implements <see cref="INotifyPropertyChanged"/>.
/// </typeparam>
/// <param name="host">The object that contains the changed property.</param>
/// <param name="numberOfEvents">The expected number of change events for
/// the specified property</param>
/// <param name="changeAction">An action that triggers the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
/// <param name="propertyName">The name of the changed property, as advertised by the
/// <see cref="INotifyPropertyChanged.PropertyChanged"/> event.</param>
public static void AssertPropertyChangedEventCount<T>(this T host, string propertyName,
                                                      int numberOfEvents,
                                                      Action<T> changeAction)
                                                      where T : INotifyPropertyChanged
{
  int eventCount = 0;

  //register handler with assertion
  PropertyChangedEventHandler handler = (sender, e) =>
    {
      //increment if the event refers to the tested property
      if (e.PropertyName == propertyName) eventCount++;
    };

  //register handler, trigger action, then deregister
  host.PropertyChanged += handler;
  changeAction(host);
  host.PropertyChanged -= handler;

  //compare counted events with expected number
  Assert.AreEqual(numberOfEvents, eventCount);
}

 

Update:

If you want to test a full set of properties of a class at once, check out Josh Twist’s ClassTester: This handy little library simplifies things remarkably when it comes to testing complete classes or even assemblies.


Author: Categories: C#, Testing Tags:
  1. December 1st, 2008 at 22:54 | #1

    Have you seen the Automatic Class Tester?

    http://www.codeplex.com/classtester

    You can just point at your classes and it will test all properties. Classes that implement INotifyPropertyChanged can be automatically tested to see if they fire the appropriate events.

  2. March 6th, 2010 at 01:22 | #2

    Where do I sign? 😉 Awesome work, thank you.

  3. rob
    June 9th, 2011 at 06:10 | #3

    using your code for WP7 testing and loving it.

    thanks!

  1. December 1st, 2008 at 11:55 | #1