TDD: Helper for checking PropertyChanged event gets raised

Today I am working on my first WPF app, using the WPF Model-View-ViewModel (MVVM) Toolkit. Naturally, we are using TDD — like ASP.NET MVC, WPF ViewModels and ICommands lend themselves very nicely to unit testing, even around difficult dependencies like OpenFileDialog.

Anyway, one problem I am seeing repeated is writing tests for PropertyChanged events firing at the correct time. This is required so that WPF views can display updated values when something changes. For a test helper, I wrote a quick disposable event listener and extension method for this:

[TestMethod]public void Should_raise_pack_path_property_changed_event(){    viewModel.AssertRaisesPropertyChangedFor("PackPath");    viewModel.OnFileSelected(@"");}

An assertion will fail if the PropertyChanged event does not fire with the correct property name. Here is the extension method:

public static class INotifyPropertyChangedExtensions{    public static void AssertRaisesPropertyChangedFor(this INotifyPropertyChanged obj,        string propertyName)    {        new PropertyChangedEventListener(obj, propertyName);    }}

… and the event listener:

/// <summary>/// Helper class for asserting a PropertyChanged event gets raised for a particular/// property. If it hasn't been called by the time this object is disposed, an /// assertion will fail.</summary>public class PropertyChangedEventListener : IDisposable{    bool wasRaised = false;    readonly string expectedPropertyName;    bool IsDisposed = false;    readonly INotifyPropertyChanged obj;    public PropertyChangedEventListener(INotifyPropertyChanged obj, string propertyName)    {        if (obj == null)            throw new ArgumentNullException("obj");        if (propertyName == null)            throw new ArgumentNullException("propertyName");        this.obj = obj;        this.expectedPropertyName = propertyName;        obj.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);    }    void OnPropertyChanged(object sender, PropertyChangedEventArgs e)    {        if (this.expectedPropertyName.Equals(e.PropertyName))            this.wasRaised = true;    }    public void Dispose()    {        Dispose(true);        GC.SuppressFinalize(this);    }    protected void Dispose(bool Disposing)    {        if (!IsDisposed)        {            if (Disposing)            {                // Cleanup references...                this.obj.PropertyChanged -= new PropertyChangedEventHandler(OnPropertyChanged);                // Assert we got called                Assert.IsTrue(this.wasRaised,                    String.Format("PropertyChanged was not raised for property '{0}'",                        this.expectedPropertyName));            }        }        IsDisposed = true;    }    ~PropertyChangedEventListener()    {        Dispose(false);    }}

It’s not fancy, and it’s probably not thread-safe, but it does the trick for our app.