• fakewin8: Easy fakes for Windows Store apps unit tests

    Published by on August 4th, 2013 10:30 pm under C#, Emerging Technology, TDD, Test Driven Development, Unit Tests

    1 Comment

    In case you are short in time, here’s the Github link: https://github.com/dschenkelman/fakewin8. Otherwise, read on.

    If you are reading this, you probably know that due to the changes in the reflection API, all unit testing libraries that depend on the creation of dynamic proxies do not work in Windows RT (for example Moq). As someone who does a lot of Windows 8 development and makes heavy use of unit tests, this was something that really changed the way I approach unit testing.

    I’ve seen many different proposals to workaround this issue, such as having linked files, having the components under test in a portable class library (and then using any mocking framework) and using public properties that expose setters for the methods to fake. While those approaches do work fine (in fact I’ve tried all of them), none of them fully suit my needs. I just did not feel completely comfortable with only one of them.  That’s why I came up with the following.

    Premises

    1. For each interface or base class, I want to create only one class that can be used as a stub/mock in any test method. This means that all methods must be easy to setup with different logic for different unit tests.
    2. No additional components should be required (i.e.: no portable class libraries, no linked files).
    3. Method invocations should be automatically tracked so assertions can be performed based on them.
    4. Fake class generation should be automatic. We want to focus on the tests development, not the fakes development.

    Proposal

    fakewin8 proposes the usage of classes like FakeAction and FakeFunc, which act as normal Action and Func, but keep track of the number invocations and parameters on each of them.

    For example, for this interface:

    public interface INavigationService
    {
        void Navigate(string view);
    
        void GoBack();
    }

    The following fake class should be created (and only this class should be required):

    public class FakeNavigationService : INavigationService
    {
        public FakeAction<string> NavigateAction { get; set; }
    
        public FakeAction GoBackAction { get; set; }
    
        public void Navigate(string viewName)
        {
            this.NavigateAction.Invoke(viewName);
        }
    
        public void GoBack()
        {
            this.GoBackAction.Invoke();
        }
    }

    The FakeAction and FakeFunc classes (at the moment they support until up to 3 parameters) can be leveraged like this in your unit tests:

    // arrange
    this.fakeNavigationService.NavigateAction = FakeMethod.CreateFor<string>(view => { });
    
    // act
    
    // assert
    Assert.AreEqual(1, this.fakeNavigationService.NavigateAction.NumberOfInvocations);
    Assert.AreEqual("ViewName", this.fakeNavigationService.NavigateAction.Invocations.ElementAt(0).FirstParameter);

    Additionally, given the path to an assembly and an output directory, you can automatically generate the fake classes.

    FakeWin8.Generator.Console.exe <dllPath> <outputDir>

    The generated code for the sample interface is the following one (no indentation yet):

    public class FakeNavigationService : INavigationService
    {
    public FakeAction<string> NavigateAction { get; set; }
    
    public FakeAction GoBackAction { get; set; }
    
    public void Navigate(string view)
    {
    this.NavigateAction.Invoke(view);
    }
    
    public void GoBack()
    {
    this.GoBackAction.Invoke();
    }
    }

    Tags: , , ,

Archives

Categories