With the add vocabulary word screen that we defined last time, we can now look at the implementation of the related view model.
As a quick recap, a view model plays a pivotal role in any WPF application (and, indeed, in any application using the MVVM architectural pattern). The view model acts as an intermediary between the current state of the application, as captured by the model, and the user interface widgets visible to the user. Each view model is therefore shaped by this tension.
View model implementation
For our “Add Word” screen, we need to start with a trio of backing fields, one for each of the data entry fields we want to have, along with a member to retain a reference to the application store (we’ll need that when we send messages).
Our constructor is simple:
When changing the Spelling
property, we need to do these things:
- Store the new value.
- Update the user interface by triggering the NotifyPropertyChanged event if the new value is different.
- Update the application state by sending a
ModifySpellingMessage
to the store
Using helper methods declared on the parent class ViewModelBase<>
that we developed earlier, the implementation is:
The Phrase
and Pronunciation
properties use the same approach.
The last thing we need (for now) is to implement the ModelUpdated()
method required by our parent class:
View model testing
Writing unit tests to ensure the view model behaves as expected was more complicated than I expected.
When I first wrote a test to ensure that the Spelling
property didn’t fire the NotifyPropertyChanged
event when the value was unchanged, I wrote this test:
This test works, but I noticed a lot of repetition as I wrote further tests. First, there was a test to ensure the event was sent when the value was changed:
Then, I found I was writing very similar tests for the Phrase
and Pronunciation
properties.
The amount of boilerplate - and the level of repetition - were both concerns. Very little changes between each of these tests. It would be easy to make a mistake writing one of the tests.
To try and reduce or eliminate this repetition, I created a helper method using some reflection:
This did make the tests shorter to write:
But it didn’t really seem that the tests were easy to read; it wasn’t clear what was actually being tested.
After taking some time away from the keyboard, I realized that most of the boilerplate was related to the NotifyPropertyChanged
event, and checking that it had (or had not) been fired.
I, therefore, created a probe that allowed me to easily hook into the event and state the required assertions:
With this probe, I was able to reduce the tests into a couple of lines that are still easy to read:
The moral of the story is that you haven’t always finished just because all your tests have been written and everything is green. Sometimes you need to revisit and simplify.
Comments
blog comments powered by Disqus