Unit testing with mvc api & ninject
Asked Answered
H

1

7

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?

Healall answered 21/10, 2013 at 9:21 Comment(0)
L
9

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>();
Lowry answered 21/10, 2013 at 10:43 Comment(1)
Thanks for your really helpful answer. That makes things a whole lot clearer nowHealall

© 2022 - 2024 — McMap. All rights reserved.