Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing with mvc api & ninject

Sorry if this comes across as a stupid question im just not sure how to get started writing some unit tests.

I have a solution containing an api and a unit test project. The api has a repository/interface used for data access using ninject.

My question is how is my best way to unit test my api controllers. I have read a little about Moq but not sure if I need to use it as I want to test against my database.

I have read that I need to use a [TestInitialize] attribute

[TestInitialize]
public void MyTestInitialize()
{
  var kernel = NinjectWebCommon.CreatePublicKernel();
  kernel.Bind<BusinessController>().ToSelf();
}

My problem is my test project cant resolve CreatePublicKernel Checking the NinjectWebCommon class in the api there is no function called CreatePublicKernel.

What am I missing here?

like image 365
Diver Dan Avatar asked Oct 21 '13 09:10

Diver Dan


People also ask

Is it possible to unit test Web API?

You can either create a unit test project when creating your application or add a unit test project to an existing application. This tutorial shows both methods for creating a unit test project. To follow this tutorial, you can use either approach.

How do I write a unit test for Web API?

Following is a very common pattern in Unit Testing. In the first step, we will have to create test data for testing, using a mock or stub object. This approach will minimize the number of dependencies. We have an option to create a Unit test project when we create a Web API project.


1 Answers

Ninject (or other DI library) is used only to provide dependencies into your controller's constructor. E.g. if you need BusinessController which requires two repositories, then controller should have constructor which expects these dependencies:

public BusinessController(IUserRepository userRepository, 
                          IOrderRepository orderRepository)
{
    _userRepository = userRepository;
    _orderRepository = orderRepository;
}

If you want to write unit tests for your controller, you should provide mocked implementations of these repositories. Use Moq or other framework for creating mocks:

var userRepositoryMock = new Mock<IUserRepository>();
var orderRepositoryMock = new Mock<IOrderRepository>();
// setup mocks here
var controller = new BusinessController(userRepositoryMock.Object,
                                        orderRepositoryMock.Object);

If you are writing integration tests for your controller, you should provide real implementations of these repositories, which use some real database.

var userRepository = new NHibernateUserRepository();
var orderRepository = new NHibernateOrderRepository();
// prepare some data in database here
var controller = new BusinessController(userRepository, orderRepository);

You can move controller instantiation into some method which is executed before each test (SetUp or TestInitialize method) in order to remove code duplication from your tests.


UPDATE: You also can use Ninject for integration testing. Just create Ninject module which will be used both by your real application and integration tests:

public class FooModule : NinjectModule
{
    public override void Load()
    {
        Bind<IUserRepository>().To<NHibernateUserRepository>();
        Bind<IOrderRepository>().To<NHibernateOrderRepository>();
        Bind<BusinessController>().ToSelf();
    }
}

Then use this module both to create kernel in NinjectWebCommon.CreateKernel method and kernel in your tests:

var kernel = new StandardKernel(new FooModule());
var controller = kernel.Get<ValuesController>();
like image 131
Sergey Berezovskiy Avatar answered Sep 27 '22 19:09

Sergey Berezovskiy