Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Using JustMock and Dependency Injection to Mock Data Providers

0.00/5 (No votes)
13 Jan 2015CPOL2 min read 7.3K  
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:

C#
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:

C#
[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 it's 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:

C#
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:

C#
[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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)