在MVC 4中使用Ninject进行单元测试

use*_*388 9 c# unit-testing ninject ninject.web.mvc asp.net-mvc-4

我有一个叫解MvcContacts与MVC 4项目名为MvcContacts并命名为单元测试项目MvcContacts.Test(当我在Visual Studio中选中"启用单元测试"框会自动创建.

我将Ninject.MVC NuGet包安装到MvcContacts(MVC项目)中.

我遵循了本教程,我已经完成了所有设置而没有错误,它应该可以正常工作; 但是,我的单元测试项目MvcContacts.Test有这样的错误:

'MvcContacts.Controllers.HomeController'不包含带0参数的构造函数

这是我的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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何让我的单元测试项目与Ninject一起工作?

Ste*_*ble 10

您需要Logging.ILogger在单元测试中将实例传递给构造函数.您可以新建一个实现某种类型的实例Logging.ILogger,也可以使用像Moq这样的库来创建一个模拟实例:

var mockLogger = new Moq.Mock<Logging.ILogger>();
var controller = new HomeController(mockLogger.Object);
Run Code Online (Sandbox Code Playgroud)

或者,您可以为您的HomeController以下内容添加默认构造函数:

public HomeController() { _logger = new /* create logger */; }
Run Code Online (Sandbox Code Playgroud)

编辑

如果你想Kernel在你的测试中使用你的Ninject ,你可以这样做,但我认为这对于这个简单的案例来说太过分了.

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

如果你想要一些非常神奇的注入,你也可以使用Ninject 的MockingKernel扩展,但这几乎肯定是矫枉过正的.

  • @SteveRuble:除非你有依赖层.如果我需要模拟类A注入到类B中,然后将其注入到类C中,您仍然必须以某种方式测试类C**,这意味着手动解析依赖项或使用Ninject之类的东西.当然,除了C之外的所有东西都是模拟的,但你仍然需要注入那些模拟. (3认同)