Simplifying unit tests for WPF ViewModels

TL;DR: use custom assertion extensions to easily unit-test implementations of INotifyPropertyChanged.

In WPF applications employing the MVVM design pattern most view models will implement the INotifyPropertyChanged interface. Unit-testing the correct implementation for each and every view model property is just as drab as auto-generating the code providing that implementation. Of course you can decide that you cannot be bothered and just not test the INotifyPropertyChanged behavior. But in my experience bugs will creep in as soon as that default code is changed. Going full circle from bug report to fix to code review to deployment is much more expensive than to just write the damn tests. But for that to realistically happen there must be a way to write those test with minimal effort.

The tests need to cover several aspects of the standard behavior:

  • after setting a different value, the getter must return the new value
  • when setting a different value, a PropertyChanged event must be fired
    • exactly once
    • with the view model instance as its source
    • with the name of the changed property in the PropertyChangedEventArgs
  • when setting the same value, no PropertyChanged event may be fired

So, how can we simplify those tests sufficiently for developers to actually write them and for them to be readable and maintainable afterwards? You would think with a standard problem like that, there would be a well-known library out there doing the job for you. I have however not found one yet. Please comment if you know one, since I have already written test helpers and assertion extensions for this very standard behavior multiple times for different clients.

As an example, I have published an extension for the popular FluentAssertions assertion library on my github page. You can check it out from the FluentAssertions.WpfExtensions repository .

It enables you to write a test for a single property like this:

viewModel.Should().ExposeNotifyPropertyChangedBehaviorFor(vm => vm.SomeProperty, "some_different_value_to_set");

providing just two things: an expression identifying the property to test and a value different from the current property value. The extension will then test all the aspects mentioned above.

I think you can be bothered to write a one-line test per property 😉