Using JustMock and Dependency Injection to mock data providers

Justmock is an excellent, fairly new, mocking framework from Telerik that I had the pleasure of getting a free licence for at the launch event.  The company I work for has now picked this up and is intending on rolling it out across the development department and I don’t think it can happen soon enough.  This is a conversation I have just had (edited and redacted for this blog) with a colleague about using it to mock up the fetching of data.

The current set up was similar to this much more contrived example but it serves to demonstrate the changes we made.

We had a class that depended on the data provider to access the database and return actual values to verify a method was working.  For this example I am using simple number checking but the actual problem was much larger.  The data provider fetches a list of numbers based on an initial value and then the checker returns the maximum value in the results set.  The data provider interface and checker are below.

public interface IDataProvider
{
    List GetNumbers(int start);
}

public class DataProvider : IDataProvider
{
    public List GetNumbers(int start)
    {
        var list = new List();
        // Use EF to access db and return list based on parameter
        // return a new list for this example
        return list;
    }
}

public class NumberChecker
{
    public int Getmax()
    {
        IDataProvider dp = new DataProvider();
        return dp.GetNumbers(5).Max();
    }

    public List GetNumbers()
    {
        IDataProvider dp = new DataProvider();
        return dp.GetNumbers(5);
    }
}

This is very simple code and the associated test went something like this.

[TestMethod()]
public void CheckCheckGeneratorReturnsMaximumValue()
{
    NumberChecker checker = new NumberChecker();
    int expected = checker.GetNumbers().Max();
    int actual = checker.Getmax();
    Assert.AreEqual(expected, actual);
}

This test passes but its not very nice.  It calls the generator methods twice and then continues to touch the database in order to get the data.

We really wanted to use JustMock so we broke it out and installed it on his machine.

To refactor this code into something testable we first had to remove that dependency on the data provider. The fact that it has an interface makes this much easier as we can simply inject an implementer of this interface into the method and act on that.  So without changing the implementation of the data provider and the interface the NumberChecker class became the following.

public class NumberChecker
{
    public int Getmax(IDataProvider dp)
    {
        return dp.GetNumbers(5).Max();
    }

    public List GetNumbers(IDataProvider dp)
    {
        return dp.GetNumbers(5);
    }
}

Here we have moved the data provider up to a parameter and are now able to inject any implementer we choose into this method.

This now allows us to test these methods without accessing the data or the real data provider (as we are not testing that here).

JustMock has a method that allows you to return any value when calling a method on a mocked object (Returns).  Using this we can mock up our data provider to do something that we want it to do rather than access the database.  This then allows us to return a custom value so the test now becomes:

[TestMethod()]
public void CheckCheckGeneratorReturnsMaximumValue()
{
    // ARRANGE
    // Create a new list of integers to use as the returns value
    var ints = new List { 1, 2, 3, 4, 5 };

    // Create the data provider object and set it up so that GetNumbers method
    // always returns the list we created above.
    var provider = Mock.Create();
    Mock.Arrange(() => provider.GetNumbers(Arg.IsAny<int>())).Returns(ints);

    // ACT
    // Run the NumberChecker method passing in our mocked data provider
    NumberChecker checker = new NumberChecker();
    int actual = checker.Getmax(provider);

    // ASSERT
    int expected = 5;
    Assert.AreEqual(expected, actual);
}

As we can now see passing in the data provider instance from here makes the test much easier to understand.  We have created a new list of integers and are simply returning this from the method on the data provider that we pass in to our NumberChecker.

Advertisements

About Leom Burke
Working for a healthcare company in the UK with a focus on C#/WPF/WCF/EF. Personally I also enjoy working with ASP.NET (MVC), ruby and investigating best practice using methods like TDD and bettering the quality of code. This is personal blog and as such has no relationship to the thoughts, views and feelings of the company I happen to be working for.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: