【问题标题】:Unit Testing with Ninject in MVC 4在 MVC 4 中使用 Ninject 进行单元测试
【发布时间】:2013-09-13 17:35:30
【问题描述】:

我有一个名为 MvcContacts 的解决方案,其中有一个名为 MvcContacts 的 MVC 4 项目和一个名为 MvcContacts.Test 的单元测试项目(在我检查了 Visual Studio 中的“启用单元测试”框。

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

我关注了this tutorial,我已经完成了所有设置,没有任何错误,它应该可以正常工作;但是,我的单元测试项目 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();
        }
    }
}

这是我的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);
        }
    }
}

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

【问题讨论】:

    标签: c# unit-testing asp.net-mvc-4 ninject ninject.web.mvc


    【解决方案1】:

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

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

    或者,您可以将默认构造函数添加到您的HomeController

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

    编辑

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

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

    如果您想要一些真正神奇的注入,您也可以为 Ninject 使用 MockingKernel 扩展名,但这对于这种情况几乎肯定是矫枉过正。

    【讨论】:

    • 谢谢,我会试试这个,但如果我必须手动解决依赖关系,那么 Ninject 有什么用?我认为 Ninject 的主要好处之一是它有助于单元测试。
    • @user1477388,使用控制反转/依赖注入模式可以更轻松地进行单元测试,但是如果您的单元测试非常复杂以至于您需要使用 IoC 容器 (Ninject) 来设置依赖项那么你的单元测试可能太复杂了。 ideal 单元测试仅使用一个“真实”实例(例如,HomeController),所有其他依赖项均作为模拟提供。
    • @SteveRuble:除非你有多层依赖。如果我需要模拟 A 类以注入 B 类,然后将 B 类注入 C 类,您仍然需要测试 C 类以某种方式,这意味着手动解决依赖关系或使用类似 Ninject 的东西。当然,除了 C 之外的所有东西都是 mock,但你仍然需要注入这些 mock。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多