C# WebApi Unit Testing and Mocking Controllers

oSR picture oSR · Aug 3, 2012 · Viewed 25.4k times · Source

I am working on this WebAPI project and I need to create unit tests for it. The base of the project was created using VS 2010 , and then an WebApi Module was added.

The workings of the controller are kinda getting in the way of testing/mocking. I am using xUnit and Moq , but there is absolutely no need to stick with those two.

The application uses specific objects to deal with database access, so I have the controllerObject and its contructor requires the DataAccessObject

I am having problem with mocking the controller / dataaccess pair. The first test i´m trying to run is a GetAllFromDataBase, but i dont really have a clue on how to do it.

EDIT:

I did what Cuong Le told me and the whole is moving now, i really apreciate it. But i stumped into another problem. To access the API, there is a username/password pair and my controller uses Thread.CurrentPrincipal.Identity.Name; right now i would need to set this value for it to fully work I guess.

Also the valueServiceMock.Setup(service => service.GetValues()) .Returns(new[] { "value1", "value2" });

does not seem to be working. as the code tries to reach for the database, and gets nothing since it cant get a valid username to look for

Answer

cuongle picture cuongle · Aug 4, 2012

In order to get your app testable, you need to design for testability in mind.Technically, to design to testability, your app should be loose coupling as much as possible between layers, between components and even between classes.

A lot of hints to design for testability: avoid sealed, static class... But the most popular thing you need to be aware of is dependency injection pattern, instead of creating object inside contructors or methods of other objects, this object should be injected. With this way we make loose dependency between class and easy for us to fake by mocking framework. Esp, for the objects which depend on external resource: network, file or database.

How to inject object by using dependency injection: that's why IocContainer is the right tool for this, it will inject objects for you automatically. IoC Container which I prefer to use is: Autofac and NInject.

Example in here to inject ValueService into ValuesController:

public class ValuesController : ApiController
{
    private readonly IValueService _valueService;

    public ValuesController(IValueService valueService)
    {
        _valueService = valueService;
    }

    public string[] Get()
    {
        return _valueService.GetValues();
    }

    public string Get(int id)
    {
        return _valueService.GetValue(id);
    }
}

And below is the simple code to unit test with Moq:

var valueServiceMock = new Mock<IValueService>();
valueServiceMock.Setup(service => service.GetValues())
            .Returns(new[] { "value1", "value2" });

var controller = new ValuesController(valueServiceMock.Object);
var values = controller.Get();

Assert.AreEqual(values.Length, 2);
Assert.AreEqual(values[0], "value1");
Assert.AreEqual(values[1], "value2");