Unit Testing ViewModels In Prism Modules

PRISM + WPF = MVVM

All of my recent projects at work have been WPF  applications designed using the Microsoft PRISM framework for composite/modular applications.  PRISM provides the ability to modularize our applications into separate UI modules that are decoupled from the main application and they are developed in a separate project and compiled into their own dll.  The UI module project has a bootstrapper class (of sorts) that implements the IModule interface, and in doing so, registers its views with a region in the main window.  So basically, if the dll is there then the content will show up in the main UI and if it is not, it won’t.  This is an over simplification but I am just trying to provide some context for the main issue that I want to post about.  Let us look at a simple example, a configuration/settings module.  We would have a main region (see the web for more information on Prism Regions) that is likely a tab control with a tab for each major piece of the user interface, i.e. a Reports tab, a Help tab, etc.  The settings module would be a separate project and show up in the main window as its own tab.  PRISM will only show the settings module/tab if its dll is found in the bin of the application.  The settings bootstrapping class tells PRISM that it has views and which region within the main window’s layout to which the view should be linked.  Here is some code:


[Module(ModuleName = "SettingsModule")]
[ModuleExport(typeof(SettingsModule), InitializationMode = InitializationMode.WhenAvailable)]
public class SettingsModule : IModule
{
    private readonly IRegionViewRegistry _regionViewRegistry;

    [ImportingConstructor]
    public SettingsModule(IRegionViewRegistry registry)
    {
        _regionViewRegistry = registry;
    }

    public void Initialize()
    {
        _regionViewRegistry.RegisterViewWithRegion(RegionNames.NavigationRegion, typeof(SettingsViewItemControl));
        _regionViewRegistry.RegisterViewWithRegion(RegionNames.MainRegion, typeof(SettingsView));
    }
}

This is a simple implementation of the Microsoft.Practices.Prism.Modularity.IModule interface within PRISM framework.  This interface tells PRISM that this is a UI module and should be made available.  Note now the SettingsView is registered with the Main Region, which in our MainWindow xaml is a tab control marked as a PRISM region using a special attribute.

Okay, enough background.  I think it is safe to assume some familiarity with these topics or else you would not be reading this type of post.  I want to just share some experiences I had recently while writing unit tests for my “Settings Module” (the names and code types have been changed to protect the innocent).  It has never come easy, thought-process-wise, when I went to write some unit tests for my user interface classes.  So, I am posting about that thought process and sharing the resulting unit tests.  I realize that I have virtually zero audience for my blog, but on the off chance that some other developers do read this, I would sincerely benefit from any constructive feedback on my process and my unit tests.  Unit testing is a big part of my work (as it should be for all developers, right?) and I have been focusing my studies (recently, The Art of Unit Testing 2nd Ed., Roy Osherove) on this area and on the improvement of my unit tests, both in best practices and in code coverage.  So…

Solution Structure

My latest feature/task at work was a configuration module (and the service that supports it) for another WPF, touch-first, application, using all of the latest goodies (Entity Framework, MEF, PRISM, .NET 4.5).  The requirements indicated that I would have a tabbed user interface with about a half-dozen different tabs, each containing a logical group of application settings that the user should be able to edit.  I set up a main settings view that held a tab control and defined a local region so that I could separate each settings tab into its own view/view model pair.  This allowed me to maintain consistency with the design of the other UI modules and with our normal best MVVM practices.  Each settings tab had a view which contains the xaml for the ui and a view model class that defines the interaction logic for the view.  So, for example, the first settings tab would consist of UserManagementSettingsView.xaml and UserManagementSettingsViewModel.cs.  Just for some further context the solution/project structure might look like this:

SolutionExplorerScreenShot

This, of course, is just a sample structure that I just created in an empty/new solution so that I could grab a screen shot of it for this article.  I do not want to use actual code/solution from my work as it is all protected by confidentiality and it is all considered a work product that is owned by our clients, not by myself.  Don’t want to get myself into any trouble.  But, that said, I think that you can get the idea form this sample structure.  The Modules.Settings project is laid out like all of the other ui modules that I might make for an application.  There are directories for views, view models and controls, with the SettingsModule.cs class in the root of the project.  This is the bootstrapper for the module and where the above shown code might live, implementing the IModule interface and tying the various views in the ui module to their respective regions in the layout.  In the case of our example “Settings” module I would make a containing view for the modules content that is a tab control and would define a local PRISM region called Settings region.  Each of the individual settings views, i.e. ReportSettingsView would then be registered with the SettingsRegion and would consequently show up in the tab control that is defined in SettingsView.xaml.  So I would end up with a Settings view that was filled with various settings tabs.  All nice and structured.

You might also note there is a ViewModels directory within the module project where all of the ViewModel classes live.  Each view has a corresponding view model class, named accordingly.  This is typical of the MVVM design pattern that PRISM employs.  Each view’s view model contains properties that define any values and/or commands that are used to create the view.  So, for instance, in a ReportSettingsView I might want to display settings for Default Printer, Default Paper Size, and other reports related settings.  Consequently the ReportSettingsViewModel class would have properties for these values that bind to the xaml in the view and that is how data is displayed.  This binding and population of values in the view is fundamental to the MVVM pattern.  There is nothing in the view’s code-behind except coded to tie the view model in and a call to InitalizeComponents which creates the views content.

The unit tests that are needed for this type of UI module class library center around the view model classes, not the views.  The views themselves have very little code, as I mentioned, only what is needed to set the view model to the right type and to initialize the xaml.  All of the unit test fixtures will be matched to view model types, not to the view types.  Therefore I will have a unit test project called WpfApplication1.Modules.Settings.Tests that corresponds to this class library and that will contain all of the test fixtures.  Here is another shot of the structure for the unit test project for this ui module.

SolutionExplorerScreenShot2

Notice that the structure of the test project matches that of the module’s class library project shown in the previous screenshot.  Any test fixture class is located in the same place within that structure, so all of the view model fixtures are in the ViewModels directory the same as the view model classes themselves are.  This is a habit I have always had, not sure where I picked it up, that makes it easy to match a test fixture to a class.  The employed naming conventions also go to that end, the word Test or Tests is added to the tested unit’s name so that matching tests to units is that much easier.

Notice also, that there are no test fixture classes for the views, and no Views directory within the Test project’s structure.  Again, the views are not unit tested.  There isn’t really anything to test in them.  Just to prove that point, for anyone that may doubt that, here is the code behind for one of our example views:


namespace WpfApplication1.Modules.Settings.Views
{
    /// <summary>
    /// Interaction logic for SettingsView.xaml
    /// </summary>
    public partial class SettingsView
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SettingsView"/> class.
        /// </summary>
        [ImportingConstructor]
        public SettingsView()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Sets the view model using MEF import.
        /// </summary>
        [Import]
        public SettingsViewModel ViewModel
        {
            set
            {
                this.DataContext = value;
            }
        }
    }
}

You can see that there is nothing to unit test here.  Both the constructor and the single write-only property are handled by MEF importing.  MEF is used through out the solution to matching views to view models in this fashion.  The data context for each view’s binding is imported using MEF Import attribute on the ViewModel property that is setup for each view.  This plumbing is part of setting up each view and cannot be overlooked.  It is also possible to use Unity Dependency Injection with PRISM and many people do.  Also it is possible to use PRISM with MEF for modularity and Unity for dependency injection, together but that is a debate for another time.

Unit Testing the View Models

So when the time comes to unit test my ui modules I previously have dreaded it, not sure why, mainly because it just hasn’t come naturally to me.  Usually when writing unit tests for, let us say an application service, it just flows.  I am able to easily see what should be tested and fairly easily write the tests.  The only issues being making sure that I am able to mock my dependencies easily.  But for view models it isn’t as simple.  I am never sure just what should be tested and how to test it.  So let us look at some examples.  First, here is a view model for one of my settings views:


[Export]
[HasSelfValidation]
public class VolumeSettingsViewModel : BaseSettingsViewModel<VolumeSettingsViewModel>
{
    private decimal _macroMinimumFlushVolume;

    private decimal _macroMinimumPrimeVolume;

    private decimal _manifoldMinimumFlushVolume;

    private decimal _microMinimumFlushVolume;

    private decimal _microMinimumPrimeVolume;

    /// <summary>
    /// Initializes a new instance of the <see cref="VolumeSettingsViewModel"/> class.
    /// </summary>
    /// <param name="serviceAggregator">The service aggregator.</param>
    /// <param name="settingsController">The settings controller.</param>
    [ImportingConstructor]
    public VolumeSettingsViewModel(IServiceAggregator serviceAggregator, ISettingsController settingsController)
        : base(serviceAggregator)
    {
        DisplayName = Resources.Properties.Resources.VolumeSettingsView_DisplayName;

        settingsController.RegisterSettingsViewModel(this);

        RegisterProperties();
        Initialize();
    }

    [RangeValidator(typeof(decimal), Constants.MinMacroFlushRange, RangeBoundaryType.Inclusive, Constants.MaxMacroFlushRange,
        RangeBoundaryType.Inclusive, MessageTemplateResourceName = "VolumeView_RangeErrorMessage",
        MessageTemplateResourceType = typeof(Res))]
    public decimal MacroMinimumFlushVolume
    {
        get
        {
            return _macroMinimumFlushVolume;
        }
        set
        {
            if (value.Equals(_macroMinimumFlushVolume))
            {
                return;
            }
            _macroMinimumFlushVolume = value;
            RaisePropertyChanged(() => MacroMinimumFlushVolume);
            IsDirty = true;
        }
    }

    [RangeValidator(typeof(decimal), Constants.MinMacroPrimeRange, RangeBoundaryType.Inclusive, Constants.MaxMacroPrimeRange,
        RangeBoundaryType.Inclusive, MessageTemplateResourceName = "VolumeSettingsView_RangeErrorMessage",
        MessageTemplateResourceType = typeof(Res))]
    public decimal MacroMinimumPrimeVolume
    {
        get
        {
            return _macroMinimumPrimeVolume;
        }
        set
        {
            if (value.Equals(_macroMinimumPrimeVolume))
            {
                return;
            }
            _macroMinimumPrimeVolume = value;
            RaisePropertyChanged(() => MacroMinimumPrimeVolume);
            IsDirty = true;
        }
    }

    [RangeValidator(typeof(decimal), Constants.MinManifoldFlushRange, RangeBoundaryType.Inclusive, Constants.MaxManifoldFlushRange,
        RangeBoundaryType.Inclusive, MessageTemplateResourceName = "VolumeSettingsView_RangeErrorMessage",
        MessageTemplateResourceType = typeof(Res))]
    public decimal ManifoldMinimumFlushVolume
    {
        get
        {
            return _manifoldMinimumFlushVolume;
        }
        set
        {
            if (value.Equals(_manifoldMinimumFlushVolume))
            {
                return;
            }
            _manifoldMinimumFlushVolume = value;
            RaisePropertyChanged(() => ManifoldMinimumFlushVolume);
            IsDirty = true;
        }
    }

    [RangeValidator(typeof(decimal), Constants.MinMicroFlushRange, RangeBoundaryType.Inclusive, Constants.MaxMicroFlushRange,
        RangeBoundaryType.Inclusive, MessageTemplateResourceName = "VolumeSettingsView_RangeErrorMessage",
        MessageTemplateResourceType = typeof(Res))]
    public decimal MicroMinimumFlushVolume
    {
        get
        {
            return _microMinimumFlushVolume;
        }
        set
        {
            if (value.Equals(_microMinimumFlushVolume))
            {
                return;
            }
            _microMinimumFlushVolume = value;
            RaisePropertyChanged(() => MicroMinimumFlushVolume);
            IsDirty = true;
        }
    }

    [RangeValidator(typeof(decimal), Constants.MinMicroPrimeRange, RangeBoundaryType.Inclusive, Constants.MaxMicroPrimeRange,
        RangeBoundaryType.Inclusive, MessageTemplateResourceName = "VolumeSettingsView_RangeErrorMessage",
        MessageTemplateResourceType = typeof(Res))]
    public decimal MicroMinimumPrimeVolume
    {
        get
        {
            return _microMinimumPrimeVolume;
        }
        set
        {
            if (value.Equals(_microMinimumPrimeVolume))
            {
                return;
            }
            _microMinimumPrimeVolume = value;
            RaisePropertyChanged(() => MicroMinimumPrimeVolume);
            IsDirty = true;
        }
    }

    protected override sealed void Initialize()
    {
        base.Initialize();
    }

    protected override sealed void RegisterProperties()
    {
        RegisterProperty(() => MicroMinimumPrimeVolume);
        RegisterProperty(() => MacroMinimumPrimeVolume);
        RegisterProperty(() => MacroMinimumFlushVolume);
        RegisterProperty(() => MicroMinimumFlushVolume);
        RegisterProperty(() => ManifoldMinimumFlushVolume);
    }

    #endregion
}

This is a new view called VolumeSettingsView that allows the user to setup some minimum volume amounts for a dispensing device.  I have altered it a little bit in order to simplify and somewhat obscure its real purpose.  I did not want to have to completely write a new view and view model so this is from a work project but as I said, I have kind of dumbed it down a bit.  But as you can see from the view model code, there are 5 values for the user to edit and they are represented by properties on the view model.  There is also some plumbing code in the form of the BaseSettingsViewModel.  The base class implements the connection to the service class that provides and stores these values.  I will not go into how it all works, but generally speaking it uses reflection to pull setters and getters for both the view model and the target service so that the updating of values to/from the service is done by the base class and can be re-used for all of the settings view models.  Pretty sweet.  The last method, RegisterProperties is what sets this all up.  The lambda expressions passed in are used to reflect the getters and setters so that it can all be automated.  Anyways, lets get to some unit tests.  I never have seen the need to unit test C# and .NET library code as that is handled by the authors at Microsoft, so no need to exercise the getters and setters for the view model properties, so let us start with the constructor.  That is usually my first point of entry when I am starting my unit tests.  So,

What does the constructor do?  Let us look at the code:


/// <summary>
/// Initializes a new instance of the <see cref="VolumeSettingsViewModel"/> class.
/// </summary>
/// <param name="serviceAggregator">The service aggregator.</param>
/// <param name="settingsController">The settings controller.</param>
[ImportingConstructor]
public VolumeSettingsViewModel(IServiceAggregator serviceAggregator, ISettingsController settingsController)
    : base(serviceAggregator)
{
    DisplayName = Resources.Properties.Resources.PrimeFlushSettingsView_DisplayName;

    settingsController.RegisterSettingsViewModel(this);

    RegisterProperties();
    Initialize();
}

a. First we set a DisplayName property from a resource string.  This is a base class property that happens to be the text for the tab item, but it needs to be set, so we can test that.

b.  Second, a method on the settings controller class is called to register the view model with the controller.  In this particular implementation I used a controller class for the module.  I do not always do this, only when necessary.

In this case, because the settings are spread across several views, I needed a place to coordinate the saving and initialization and other things for all of the settings in one place.  So, I added a controller.  The settings controller handles the save button for all of the settings tabs together.  It checks with each one to see if the values have changed and are valid, so that if the user clicks okay on the confirmation dialog, the save can be performed on all settings view models.  That is where the register method comes in.  Accepting any instance of IBaseSettingsViewModel, it can manage a list of all of them.  Without, I might add, any of the individuals knowing about each other.  One of the caveats that must be dealt with when using this setup is that due to the loosely coupled views and view models, and due to the fact that they are all imported using MEF, no one class knows about any of the others.  There wasn’t anywhere to manage all of the separate view models, hence a controller class.  The controller is made aware of the view model only when the view model says “Here I am” by registering.  This maintains the loose coupling.  I could remove any one of the settings views and its view model and the module would still perform with those that remain.  The controller doesn’t care how many view models register with it and will handle them all the same.  Similarly, I could add a new settings tab view/viewmodel and as long as it implements the base interface and registers with the controller, then what ever settings values it exposes can become part of the validation and saving process when the user hits the save button.

So now we can write tests for the constructor.  We will test that the display name property is set and that the view model registers with the controller.  Makes sense to me anyways…


[TestClass]
public class VolumeSettingsViewModelTests
{
    private readonly MockServices _mockServices = new MockServices();

    private readonly Mock<ISettingsController> _mockSettingsController = new Mock<ISettingsController>();

    [TestMethod]
    public void TestVolumeSettingsViewModelConstructorInitializesMembers()
    {
        // Arrangements
        _mockSettingsController.SetupAllProperties();

        // Actions
        var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object);

        // Assertions
        Assert.IsNotNull(cut);
        Assert.IsFalse(cut.DisplayName.IsNullOrEmpty());
        _mockSettingsController.Verify(c => c.RegisterSettingsViewModel(cut), Times.Once());
    }
}

A couple of things to note here.  The MockServices type is in a separate unit testing common library that holds any custom mocks that are used over multiple unit tests.  MockServices is a mock of all of the application services, including a custom event aggregator mock.  The other services are mocked using Moq which we use at work for all of our mocking needs.  It works well, is easy to use and I can say that I like it very much.  I use mocks of the application services layer so much that I wrote a class that collects them all and creates mocks of them all. Each mocked service is exposed in two ways from the MockServices class.  First as a property of the mock itself, i.e. _mockServices.DialogServiceMock, which allows me to make setup and verify calls on the mock of IDialogService.  Second as the Object needed for the service for use in passing as a parameter to constructors, etc.  For example, if I needed a mock of the dialog service to construct a view model in a unit test I could pass in _mockServices.Aggregator.DialogService and that would not pass the mock but rather the .Object property of the mock, which when using Moq is how you get the instance of the type you are mocking.

So we have tested our view model constructor by asserting that it sets a valid string to the DisplayName property and we have tested that it registered itself with the controller by using the Verfiy method on our mock of the controller (line 20).  If a verify call is not successful, a MoqException is thrown which fails the test.

2. What else can we test for?  What else does this view model do?  Well part of the way my settings models work is by registering the properties that are fed by a service, as I explained is accomplished in the BaseSettingViewModel class.  So we can test that this has occurred and is working correctly.

a. We need to setup our mock of the target service that feeds these settings values (in this case it happens to be called ConfigurationService).

b. We need to then change the values of the settings on our view model instance, so that we can…

c. Check that the values were updated on the target service successfully.

Here is the code for that unit test:


[TestMethod]
public void TestVolumeSettingsViewModelRegistersPropertiesWithService()
{
// Arrangements
const decimal TestVolumeValue = 20.5M;
_mockServices.ConfigurationServiceMock.SetupProperty(c => c.MacroMinimumFlushVolume);
_mockServices.ConfigurationServiceMock.SetupProperty(c => c.MicroMinimumFlushVolume);
_mockServices.ConfigurationServiceMock.SetupProperty(c => c.ManifoldMinimumFlushVolume);
_mockServices.ConfigurationServiceMock.SetupProperty(c => c.MacroMinimumPrimeVolume);
_mockServices.ConfigurationServiceMock.SetupProperty(c => c.MicroMinimumPrimeVolume);
_mockServices.Aggregator.ConfigurationService.MacroMinimumFlushVolume = 0;
_mockServices.Aggregator.ConfigurationService.MicroMinimumFlushVolume = 0;
_mockServices.Aggregator.ConfigurationService.ManifoldMinimumFlushVolume = 0;
_mockServices.Aggregator.ConfigurationService.MacroMinimumPrimeVolume = 0;
_mockServices.Aggregator.ConfigurationService.MicroMinimumPrimeVolume = 0;

// Actions
var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
{
MacroMinimumFlushVolume = TestVolumeValue,
MicroMinimumFlushVolume = TestVolumeValue,
ManifoldMinimumFlushVolume = TestVolumeValue,
MacroMinimumPrimeVolume = TestVolumeValue,
MicroMinimumPrimeVolume = TestVolumeValue
};
cut.SaveChanges();

// Assertions
Assert.AreEqual(
_mockServices.Aggregator.ConfigurationService.MacroMinimumFlushVolume, cut.MacroMinimumFlushVolume);
Assert.AreEqual(
_mockServices.Aggregator.ConfigurationService.MicroMinimumFlushVolume, cut.MicroMinimumFlushVolume);
Assert.AreEqual(
_mockServices.Aggregator.ConfigurationService.ManifoldMinimumFlushVolume, cut.ManifoldMinimumFlushVolume);
Assert.AreEqual(
_mockServices.Aggregator.ConfigurationService.MacroMinimumPrimeVolume, cut.MacroMinimumPrimeVolume);
Assert.AreEqual(
_mockServices.Aggregator.ConfigurationService.MicroMinimumPrimeVolume, cut.MicroMinimumPrimeVolume);
}

This code should be fairly self explanatory, with the exception of maybe the moq specific code, but a quick look at the Moq QuickStart should clear up any confusion.  Basically I have just setup the five properties on the ConfigurationService mock and then set a new value to each, then asserted that new value (set on the view model) on the service property.  Note that the setup for the properties on the ConfigurationService only sets it so that any value set to that property will be returned by the mock.  Kind of like saying, “Okay, setup this property with a get and set”.  I also set all of the properties to a default value of 0.

So, now I have tested the underlying functionality of the view model’s link to the configuration service.  What else is there to test?

3. If you remember from the listing of the VolumeSettingsViewModel you might remember that the volume properties have some validation attributes on them, and these happened to be tied to some more functionality from the BaseSettingsViewModel class that sets a HasErrors flag if the validation fails.  So, that should probably be tested too.

a. There is a RangeValidator attribute on each volume property, from the Ent. Lib Validation Block which we use for validation of domain models.

We also use it for validation of applicable view model properties.  There is in fact some builtin wiring that sets up the validation error messages for the user in the xaml as well.  This is done using a custom control template for textboxes.

b. The range validator has an upper bound limit and a lower bound limit.  I need to test both upper and lower, for each of the 5 volume properties.  So ten tests in all, one for each situation, for each property.

Here is the code for those tests:


[TestMethod]
public void TestVolumeSettingsViewModelValidationLowerRangeMacroFlush()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MinMacroFlushRange) - 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            MacroMinimumFlushVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationLowerRangeMacroPrime()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MinMacroPrimeRange) - 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            MacroMinimumPrimeVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationLowerRangeManifoldFlush()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MinManifoldFlushRange) - 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            ManifoldMinimumFlushVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationLowerRangeMicroFlush()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MinMicroFlushRange) - 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            MicroMinimumFlushVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationLowerRangeMicroPrime()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MinMicroPrimeRange) - 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            MicroMinimumPrimeVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationUpperRangeMacroFlush()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MaxMacroFlushRange) + 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            MacroMinimumFlushVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationUpperRangeMacroPrime()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MaxMacroPrimeRange) + 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            MacroMinimumPrimeVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationUpperRangeManifoldFlush()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MaxManifoldFlushRange) + 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            ManifoldMinimumFlushVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

[TestMethod]
public void TestVolumeSettingsViewModelValidationUpperRangeMicroFlush()
{
    // Arrangements
    var testVolumeValue = Convert.ToDecimal(Constants.MaxMicroFlushRange) + 1;
    SetupConfigurationServiceProperties();

    // Actions
    var cut = new VolumeSettingsViewModel(_mockServices.Aggregator, _mockSettingsController.Object)
        {
            MicroMinimumFlushVolume = testVolumeValue,
        };
    cut.Validate();

    // Assertions
    Assert.IsTrue(cut.HasErrors);
}

These tests are all very similar, varying only in which volume property is tested and whether testing the lower limit or the upper.  Each test uses the constant value that is used in the actual RangeValidator and either adds or subtracts 1 to come up with a value that is outside the limits.  Then that invalid value is set to the property on the view model.  The validate method is called and then we assert that the HasErrors flag is correctly set showing the invalid value.

Summing Up…

Well, I guess that is a pretty good glimpse at what I went through to get these view models tested.  I just wanted to provide some real world examples into how to come up with what unit tests to write for a view model.  It is something that doesn’t come as easily for me as other unit testing and I have never really found a blow by blow set of examples like what I have hopefully provided here.  In other words, I wish I would have found an article like this when I first started with PRISM and MVVM, that would have helped me with my unit testing.

Certainly nothing earth shattering, and in fact, these examples are pretty simple, but I wanted to convey the through process and the “on the ground” example of some unit testing for view models.  I could go through the rest of the view models but as they are all settings view models, the subsequent test are all very similar, as is the process behind coming up with them.

I hope that this helps someone.  And please offer some feedback if you have experience in this and can offer some insight.  I am still very much looking to improve my unit testing process and technique and all input would be appreciated.


Git Bash & Console2, Finally!

I have seen this information in various places and in various pieces and finally have taken the time and effort to put it together and implement a working solution on my work machine. First a bit of context for the situation and my motivations.

My work machine is pretty much my only machine. I have an older personal laptop that I do not use much anymore. It is a ThinkPad R50 that was manufactured in Apr. 2002, with a Centrino 1.0 ghz processor and an upgraded 2gb of RAM. It dual boots Windows XP and Ubuntu 12, and doesn’t do much more. I have Visual Studio 2010 on it and up until this time last year it was my only machine and I still worked on it about 30-35 hours per week. In all honesty I can say that it is the best laptop I have ever owned (not used) and by best I do not mean the most powerful, but just the best overall. It is a horse, I bought it used from my best friend for something like $150, but I don’t really remember. He had had it for a few years and put the extra memory in it. I have used it steadily as my only personal machine ever since and it has served me well. Okay, enough about my old laptop, as it is just that, my old laptop.

These days I am using my work machine as both my work machine and my personal machine. To qualify that however, I need to say that I do not spend an inordinate amount of time in front of it outside of work. I do use it to keep my iTunes library and sync my iPhone 4s, on which I listen to many audio books and watch many cartoon episodes. I also use it to download media and some light research. Otherwise it is work-related, to the tune of an average of 40-45 hours per week, with the 40 being billed to work. On that topic, I have been using RescueTime at the behest of Scott Hanselman, whose writing on productivity and what being a developer feels like I cannot recommend enough. So, due to RescueTime, I know a little more about how much I use my computer and what I do on it, it is really cool. Nice little summary at the end of each week, certainly helps me feel a little less guilty and a little more like I should about myself, I really do work hard.

RescueTime weekely summary email sample.

This is an example of the weekly summary I get from the RescueTime utility. This is from a week or two ago.

But, I digress. My new machine (well I have had it about 11 months and it was new when I got it) is a Dell Precision and much more of a beefcake than the thinkpad. Here are the specs, just cause I like Speccy and enjoy an excuse to use it.

2012-12-21_Dell_Speccy_screenshot

Speccy summary for my current daily, a Dell Precision M4600.

Git Bash and Console2, so what about ’em…

At work we use a product called Surround SCM (and its companion defect suite, Test Track Pro) by Seapine Software. These two products track all our work including feature requests, action items and defects, and the source itself. The products work in tandem with each other and are an integral part of our SDLC. I cannot check in any source code with out an attached item in TTP. Unfortunately, Surround uses the centralized version control system that uses the check out -> edit -> check in workflow just like visual source safe did. Where as Git, is a distributed version control system that uses a pull changes -> work -> push changes model that is much more conducive to multiple developers and branching/merging.

I use Git locally on my laptop to track changes while I am working on various tasks.  Git allows me to keep track of larger features and tasks that might take me days to complete.  I can do smaller, incremental commits and use branching to go on tangents and to handle some smaller fix that has to take priority.  All the while I keep my master branch in sync with the centralized Surround repository.  I do not push to any remote repository with Git, I simply use it to track my Source directory on my local machine.  It could be called local revision control for my working copy of the code.  That might sound complicated and like too much work that is unnecessary but I find that it is working well for me so far (it hasn’t been that long).

Enter another tool, one that I have used for a long time, several years at least, not exactly sure.  And that is a command prompt replacement for windows called Console2 that provides a tabbed command console interface with improved usability over the clunky default Windows command prompt.  I use one other console application lately that is a MinGW32 instance that is a bash shell installed with the Git for Windows package.  Now we come to the issue, and I apologize for how long it took to get here.  Console2’s tabbed interface is nice and open on my desktop most of the day but I have to use the Git Bash shortcut to open the shell for working with Git.  So I went out a few months ago and did some Googlin’ and got some instructions for setting up a Git tab withing my Console2, but it never worked right.  it would open up but would not initialize and show the prompt.  So after spending a little bit of time fooling with it I gave up and just used two separate command windows, one for Git and one for everything else (I also have a VS Command Prompt tab that works great and saves me finding the shortcut when I need it).

Console2 with lowered opacity

I have the opacity set lower when Console does not have focus.

That is, until today.  I had a very interesting day that led me down several research paths solving problems most of the day, I have actually been working, except for meal breaks, since 7am this morning (I  looked at the system clock and see that it is 12:04am, haven’t done this in a while).  I now have a working Git Bash prompt in a Console2 tab.  Alongside my VS Command Prompt tab and my Cygwin shell tab.  And, oddly, I have sat here for the last 45 minutes copying unrelated links and including way too much detail in this post just so that I could share the solution with… well, probably no one.  But maybe someone, even a few people.  I am going to include screenshots and form field values for several things, as well as links to where I found the information and that should get anyone there.

Git Bash settings in Console2

Here is the actual settings dialog with the values that work for me.

The Git for Windows package is installed in the C:\Program Files (x86)\Git directory.  Here are the settings for the Console2 tab for the Git Bash prompt:

  Title: Git Bash
Icon: C:\Program Files (x86)\Git\etc\git.ico
Shell: C:\Program Files (x86)\Git\bin\sh.exe –login -i
Startup Dir: %HOMEDRIVE%%HOMEPATH%

To the left here is the settings dialog with the above values in place where they go in the form.  These values work for me with the install directory in the previous paragraph.  It doesn’t matter where you have Console2 installed (it is standalone anyways), at least not at this point.

Next I will show you how I have setup a shortcut on my desktop that will open an instance of the Console with the Git Bash tab initialized rather than the default tab, which is just  the regular command prompt.

The desktop shortcut does, of course depend on where you have installed the Console2 directory.  I have mine installed, surprisingly enough, in the C:\Program Files (x86)\Console2 directory.  Which results in the following values for the shortcut, created blank by right-clicking on the desktop and selecting New -> Shortcut.

Git Bash Console2 Shortcut

Settings for the desktop shortcut that opens Console2 with the Git Bash tab loaded.

You need the extra set of quotes around the target value as it has separate quoted values that must be grouped with the outer quotes.  Without these extra outer quotes I was getting an error message saying that the Target value was invalid when I tried to save the shortcut.

Target: “”C:\Program Files (x86)\Console2\Console.exe” -t “Git Bash””

Start In: %HOMEDRIVE%%HOMEPATH%

Finally I will include the link where I finally found some accurate information.  My settings are different as I use some different values of course, as you well may depending on your system.  There is also another tidbit here that I have used to create a right-click shortcut, but only the one for right-clicking on a file and being offered a choice to open “Git Bash Here.”  I am not entirely sure how much I will use this one, but I went ahead and added it anyways.  Just opened Regedit and followed the instructions.

So, there it is, after too much ado.  Cheers!


C# Extension Method and Lambda Expressions

Recently I have been trying to learn more about the new language features in C# 3.0, and I have enjoyed what I have found thus far.  Especially both the var keyword and extension methods, but I had yet to really implement anything using lambdas.  That is until today…

One of the things I have done with extension methods was to implement some really sweet method argument validation stuff.  I had read several related blog entries regarding this subject and had whipped up a variation [actually just a much smaller set of what they had already come up with as my needs were much less] of their ideas for use in a project I am working on [and likely in future projects].   And, as it turns out, this same bit of features afforded me the opportunity to check out lambda expressions as well, and to hopefully this time add something of value to build on their work instead of just reusing it.

Okay so the scene is set, with me at my desk at work, coding a unit test for what I hope will be a new feature on my current project [dynamically executed reports from xml definition files, like rdl but much much simpler]…

I was about to use the argument extension methods to validate an integer that I needed to be in a certain range and it occured to me how nice it would be if I could just pass in an expression that evaluated to a boolean result similar to what I would do if I was writing in javascript.  Yeah, that would be extra nice!  So, off I went back to GOG to do some research on passing an expression as an argument to a function in C#.  My research led me straight to lambda expressions and exactly what I needed to make my new extension method work.

My goal was to be able to implement something like the following psuedo-code:

public void MyFunction(int myInt)
{
    RequireThat(myInt).MeetsCriteria("myInt > 0");
}

Thus being able to use some very smooth and descriptive code to validate my integer argument before using it in the function, or atleast something as close to that effect as I could get.

Well lambda expressions were exactly the ticket, specifically the Func<T, TResult> delegate type.  Which basically allows me to pass a method that accepts one parameter of type T and returns a result of type TResult as a parameter to another method, without defining a custom delegate type of my own.  A kinda anonymous delegate type construct if you will.  Lambda expressions use this type as an arg for the Expression<T>(Func<T, TResult) type constructor.   I have done some of this preliminary reading on Expression Trees and such and it is heady stuff, but interesting none the less.  I look forward to someday being able to apply it to a real world problem.  

But today I was able to apply lambdas to my real world problem like so:

I needed an extension method for my Generic argument wrapper that would allow me to pass in a simple expression predicate with which to validate the argument.  And here is what I came up with:

Code for MeetsCriteria extension method.

Code for MeetsCriteria extension method.

Now this code allows me to pass in a lambda expression that I wish to use to validate an integer argument for my method [or any integer for that matter].  This method was added to my existing argument validation extension methods setup as described in a previous post, already linked to a couple of times above, so it follows similar usage syntax, as such:

myIntArg.RequireThat("myIntArg").MeetsCriteria(...);

I also added a unit test for this new method into my existing test project for the rest of my validation extension methods, and so I will use that test method to show you a contextual usage of MeetsCriteria…

My unit test for MeetsCriteria method.  Testing that 21 is between 20 and 22.

My unit test for MeetsCriteria method. Testing that 21 is between 20 and 22.

So, now I have actually used lambdas in a project at work, I am so very happy with myself.  And my quest to conquer C# 3.0 features continues… J


Argument Validation using C# 3.0 extension methods

 After some research into reusable arg validation ideas on GOG (good ole google) I have found something that, after some simplification of course, will serve the projects meager argument validation needs. Actually this is a super cool trick that we can reuse any number of places from here on, if we so desire.  Here are the original posts that I read and have taken ideas from, particularly Roger Alsings articles, much thanks to him.  This technique is, IMHO, a nice way to showcase how to combine some of C#’s new features, specifically Generics from C# 2.0 and Extension methods from C# 3.0, into a nice solution to a frequent problem.  

http://rogeralsing.com/2008/05/10/followup-how-to-validate-a-methods-arguments/
http://weblogs.asp.net/fredriknormen/archive/2008/05/08/how-to-validate-a-method-s-arguments.aspx
http://www.puzzleframework.com/wikiengine/WikiPageViewer.aspx?ID=78

Using these posts and the code from a much larger api at the puzzle framework address in the quote above, i have assembled a smaller set of argument validation methods.  Roger Alsing’s puzzle framework has a full compliment of these validation methods if you are interested.  I, on the other hand swiped just a couple of his and added a couple of my own, but am using the same technique to acheive a fluent interface and also the very ingenius idea he had of using a wrapper class for the extension methods rather than extending each .NET type on its own.  Very nice work by him.  This article is simply an effort to explain how I used these articles to put together a much smaller set of validation methods for my own use in a project.  Hopefully it explains things clearly and pays sufficient homage to the ideas originator.

 

The basic premise is that now with generics and extension methods features of C# we are able to add functionality to types/classes. In this case all types, for the purpose of validating method arguments. The articles above explore this in a progressive fashion: First presenting the idea of an ArgumentHelper class that would have lots of overloads for validating various C# types, i.e. int, string, double, etc. Under this scheme you would need a separate method for each type of validation for each type. Such as:

public void RequireNotNull(int arg, string argName);
public void RequireNotNull(string arg, string argName);
public void RequireNotNull(DateTime arg, string argName);
...

This is not a bad idea, and certainly is better than writing a multiline if statement for each argument in each method in your project. Second Idea: was to use extension methods to facilitate usage syntax like:

public void MyMethod(int argument1, string argument2)
{
    // validate args
    argument1.RequireInRange(argument1, 0, 10, "argument1");
    argument2.RequireNotNull(argument2, "argument2");
}

Now this is starting to look pretty smooth, however we go one step further, combining the new features of Generics(C# 2.0) and Extension methods (C# 3.0) to get something that is SUPER smooth. The idea, which was of course new to me, is to a) create a generic type for argmuments. I used one similar to theirs, basically just a container for name and value of an argument the value being the arg itself of the type “T” as defined by the generic. Then b) use extension methods to add validation methods to this generic class, thus making them available to any type. Here is my generic argument container class that is the one extended:

public class ArgumentEx
{
    public T Value { get; set; }
    public string Name { get; set; }
    public ArgumentEx(T value, string name)
    {
        this.Value = value;
        this.Name = name;
    }   
    public static implicit operator T(ArgumentEx arg)
    {
        return arg.Value;
    }
}

This class simply wraps an argument with a generic container in essence. We set the default operator to return the arg itself (the “Value” member) and create a simple ctor. Now instead of having to write an extension method for each type we want to be able to validate (int, string, etc.) we just write one extension method for this class. First we write an extension method for the generic T type of our generic class and that will give us coverage of all types and this will always return us an instance of our new ArgumentEx type:

public static class ValidatorExtensions
{
    public static ArgumentEx RequireThat(
        this T arg, string name)</pre>
<pre style="padding-left:30px;">    {
        return new ArgumentEx(arg, name);
    }
}

Now we can call this RequireThat method from any argument we pass in to any method and we will get back our ArgumentEx class which we have extended with validation methods such as this:

[DebuggerHidden]
public static ArgumentEx NotNull(
    this ArgumentEx arg) where T : class
{           
    if (arg.Value == null)
        throw new ArgumentNullException(arg.Name);
    return arg;     // for fluency
}

This method extends the ArgumentEx type rather than the generic T type so we have all of our extension methods hanging off of the wrapper class. This setup is a touch abstract but it allows us to do super pretty things like this:

public ReportInfo(string pathToXmlFile)
    : base(null, null)         
{
    // validate args
    pathToXmlFile.RequireThat("pathToXmlFile").IsNotNull();           
}

not bad in the way of readability and extensibility too. Because the extension methods return the arg instance every time you can chain calls as well.

 

Below is the class diagram for the validation/argument extensions.  There are a few string extensions too added for convenience…

 

Class diagram for the validation extension classes.

Class diagram for the validation extension classes.

 

 

 

And here is a screenshot of the unit tests all green and pretty!

 

A screenshot of the pretty green unit test results!

A screenshot of the pretty green unit test results!

 

 

 

So now I have an easy to use and further extensible system for validating method arguments with out having to write if/throw constructs over and over inside of each method.  This promotes better code because the easier it is to validate my arguments the more likely it is that I will do a thorough job of it.


Google Base, Reporting Xml, and VS Unit Testing

I have been working on an interesting project here at work.  I had previously been working on some fixes for a windows service (written in C#) that uploaded our catalog items to Google Base, based on some logging and comparison diffs, every fifteen minutes if there were new items or updates to items.  But, with that seemingly on its way now, I was assigned this new project.  Basically I am working on a system that will allow the definition of sql queries, or data “views” via an XML schema.  Yes, I know there is already RDL for SQL Reporting Services, but that is not what they want.  They want a much, much simpler setup that will make it easier for a developer on the team to make changes to, or add a new report, by editing the XML  definition file.

So, off I go.  I started with the whiteboard notes that were put up during my initial meeting about this, and the sample XML there-in, and have tried to keep it as simple as possible.  I am using classes for each logical report entity, such as:  Report, Query, Column, Parameter, etc.  I am also using the VS unit testing framework for this project, which is something I hadn’t done previously, but wanted to.  Let me qualify that by saying up front that I am not using TDD strictly speaking.  But I am writing tests for code, classes and methods, as I go.  I must say I am quickly becoming hooked on the idea of unit testing everything, whether you are designing with TDD or not, it just makes sense, and it does honestly help with design decisions.  By testing your code as you go or before hand you get a quick look at how it will be called, which in my case where I am developing what hopes to be an api of sorts that will be extended and re-used often is a great benefit.   Read the rest of this entry »