Thursday, April 19, 2012

Using Moq for Unit Testing


Unit tests should be run in isolation. Meaning, a test method should not have to rely on database connections or other external dependencies being available. To accomplish this, the repository (or other data access) class used by a service must be mocked and injected using the service constructor.  Review this sample code:

[TestMethod]
public void GetByID_Test()
{
    var orderCode = "TestOrder";

    //Create a mock repository, and specify that the GetByID method always 
    //returns an Order object with a given order code
    var mock = new Mock<IOrderRepository>();

    mock.Setup(m => m.GetByID(It.IsAny<int>())).Returns
    (
        new Company.DataAccess.Order{OrderCode = orderCode}
    );

    //Inject the mock repository into the service using constructor
    var orderService = new OrderService(mock.Object);

    //Call the service method
    var order = orderService.GetById(4);

    Assert.AreEqual(order.OrderCode, orderCode, 
        string.Format("OrderCode {0} doesn't match the expected value {1}", order.OrderCode, orderCode));
}
All this code is doing is creating a "fake" repository using the interface, then setting up the method used by the "GetByID" service method that always returns the same value.  If desired, methods can be faked to return different values based on the parameter passed in.  Ideally, the mock repository setup would be contained in a common setup method, and each and every repository method would be setup with expected values, so it could be reused in each test method.

Yes, this adds time to your development cycle, but it makes your test methods more precise, isolating only the code it's meant to test, eliminating reliance on dependencies such as databases and any other "external" dependency.

To download and read more on Moq: http://code.google.com/p/moq

No comments:

Post a Comment