Unit Testing with Ninject in MVC 4

user1477388 picture user1477388 · Sep 13, 2013 · Viewed 9k times · Source

I have a solution called MvcContacts with an MVC 4 project named MvcContacts and a unit testing project named MvcContacts.Test (created automatically when I checked the "enable unit testing" box in Visual Studio.

I installed the Ninject.MVC NuGet package into MvcContacts (the MVC project).

I followed this tutorial and I have everything setup with no errors and it should work fine; however, my unit testing project MvcContacts.Test has errors like this:

'MvcContacts.Controllers.HomeController' does not contain a constructor that takes 0 arguments

This is my HomeController:

namespace MvcContacts.Controllers
{
    public class HomeController : Controller
    {
        Logging.ILogger _logger;

        public HomeController(Logging.ILogger logger)
        {
            _logger = logger;
        }

        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            _logger.LogMessage(ViewBag.Message);

            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

This is my HomeControllerTest:

namespace MvcContacts.Tests.Controllers
{
    [TestClass]
    public class HomeControllerTest
    {
        [TestMethod]
        public void Index()
        {
            // Arrange
            HomeController controller = new HomeController(); // error on this line

            // Act
            ViewResult result = controller.Index() as ViewResult;

            // Assert
            Assert.AreEqual("Modify this template to jump-start your ASP.NET MVC application.", result.ViewBag.Message);
        }

        [TestMethod]
        public void About()
        {
            // Arrange
            HomeController controller = new HomeController(); // error on this line

            // Act
            ViewResult result = controller.About() as ViewResult;

            // Assert
            Assert.IsNotNull(result);
        }

        [TestMethod]
        public void Contact()
        {
            // Arrange
            HomeController controller = new HomeController(); // error on this line

            // Act
            ViewResult result = controller.Contact() as ViewResult;

            // Assert
            Assert.IsNotNull(result);
        }
    }
}

How can I make my unit testing project work with Ninject?

Answer

Steve Ruble picture Steve Ruble · Sep 13, 2013

You need to pass an instance of Logging.ILogger to your constructor in your unit test. You can either new up an instance of some type that implements Logging.ILogger, or you could use a library like Moq to create a mock instance:

var mockLogger = new Moq.Mock<Logging.ILogger>();
var controller = new HomeController(mockLogger.Object);

Alternatively, you could add a default constructor to your HomeController:

public HomeController() { _logger = new /* create logger */; }

Edit

If you want to use your Ninject Kernel in your testing, you can do that, but I think it would be overkill for this simple case.

var module = new /* your module, or a test module which configures mocks */;
var kernel = new StandardKernel(module);
var controller = kernel.Get<HomeController>();

You can also use the MockingKernel extension for Ninject if you want some really magical injection, but that is almost certainly overkill for this situation.