【问题标题】:Property inject in unittest with ninject使用 ninject 在单元测试中注入属性
【发布时间】:2014-08-21 15:21:03
【问题描述】:

我有一个标准 MVC 5 Web 应用程序的简单控制器。我安装了 MVC 5 Ninject nuget 包。我创建了一个构造函数,并注入了我定义的接口。如果我创建一个公共属性,它也会被注入。

现在,当我创建一个 unittest 项目并想要测试 mvc 控制器时。我怎样才能做到这一点?我必须创建一个内核。内核被创建,如果我得到我的 IPersonComponent 的实例,它就会被创建。但是为什么我的财产没有被注入呢?

我创建了两个选项,但我都得到了 nullreference 异常...

界面:

public interface IPersonComponent
{
    void DoSomething();
}

实施:

public class PersonComponent : IPersonComponent
{       public void DoSomething()
    {
        throw new NotImplementedException("The method is fired but not implemented");
    }
}

测试初始化​​:

private IKernel _kernel;

[TestInitialize()]
public void Initialize()
{
    _kernel  = new StandardKernel();
}

选项 1

运行良好的控制器:

public class HomeController : Controller
{
    private readonly IPersonComponent _component;

    public HomeController(IPersonComponent component)
    {
        _component = component;
    }
}

单元测试失败,因为 PersonComponent 为空:

[TestClass]
public class HomeControllerTest
{
    [Inject]
    public IPersonComponent PersonComponent { get; set; }

    [TestMethod]
    [ExpectedException(typeof(NotImplementedException))]
    public void Index()
    {
        // Arrange
        HomeController controller = new HomeController(PersonComponent);

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

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

选项 2

控制器:

public class HomeController : Controller
{

    [Inject]
    public IPersonComponent PersonComponent { get; set; }

    public HomeController()
    {

    }

    public ActionResult Index()
    {
        PersonComponent.DoSomething();

        return View();
    }
}

测试:

[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public void Index()
{
    // Arrange
    HomeController controller = new HomeController();

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

    // Assert
    Assert.IsNotNull(result);
}

这行得通: 但为什么它会起作用?为什么不自动注入?

[TestMethod]
public void TestDoSomething()
{
    var kernel = new StandardKernel();

    var comp = kernel.Get<IPersonComponent>();
    comp.DoSomething();
}

根据答案编辑:

选项 1

    [TestMethod]
    [ExpectedException(typeof(NotImplementedException))]
    public void Index()
    {
        _kernel.Inject(this);

        // Arrange
        HomeController controller = new HomeController(PersonComponent);

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

        // Assert
        Assert.IsNotNull(result);
    }

选项 2

[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public void Index()
{
    // Arrange
    HomeController controller = _kernel.Get<HomeController>();

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

    // Assert
    Assert.IsNotNull(result);
}

【问题讨论】:

    标签: c# asp.net-mvc dependency-injection ninject


    【解决方案1】:

    在选项 1 中:MsTest 不会调用 Ninject 来告诉它向您的对象注入服务。

    在选项 2 中:您正在手动创建控制器 (new HomeController()),并且您没有告诉 Ninject 将服务注入您的对象。

    尽管 Ninject 所做的大部分事情看起来都很“神奇”,但仍然必须调用它才能将值注入到您的组件中。 ASP.NET MVC 有一个 Ninject 自身绑定的机制,因此控制器的构造由 Ninject 自动处理。这给您的印象是 Ninject 能够毫不费力地将值注入任何东西。但是 MSTest 没有类似的机制,所以你必须手动完成一些工作。

    如果您可以访问已配置的 ninject 内核,您可以说:

    HomeController controller = kernel.Get<HomeController>();
    

    或者,在选项 1 中,您可以说:

    public HomeControllerTest()
    {
        kernel.Inject(this); // populate my [Inject] properties
    }
    

    我应该提到,如果您基于真实绑定注入依赖项,那么您实际上并不是在编写“单元测试”,而是在编写“自动化验收测试”。如果您想测试独立于其依赖项的控制器操作的行为,请学习如何“模拟”其依赖项。

    【讨论】:

    • 你说得对,它不是单元测试。更多的是尝试,它是正式的集成测试。如果这是您的意思,您可以检查我的编辑吗?谢谢!
    • 另外,你有kernel.Inject(this)文档的链接吗?
    • 我实际上不认为它在文档中“详细地”解释,但github.com/ninject/ninject/wiki/Injection-Patterns 解释了它。在此处提到的文档中:github.com/ninject/ninject/wiki/Injection-Patterns 和
    • @RalphJansen:是的,你的编辑是我的想法。那样有用吗?我建议使用选项 2,但将 HomeController 恢复为使用在选项 1 中所做的构造函数注入。
    • 谢谢。是的,我们就像选项 1 一样拥有它,但只是在没有引导程序的情况下手动计算出来;)
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多