【问题标题】:When using Ninject for dependeny injection is it best practices to use Ninject in your unit tests or use a mocking framework使用 Ninject 进行依赖注入时,最好在单元测试中使用 Ninject 还是使用模拟框架
【发布时间】:2015-04-26 15:24:52
【问题描述】:

我正在使用 ninject 在我的生产环境中注入依赖项。在编写单元测试时,我看到了两种选择。我可以创建具体的类并使用 ninject 注入它们,或者我可以使用像 mock 这样的模拟框架。

我的想法是同时使用两者,并决定是否可以以可重用的方式构造 TestInterface。这样我们就不会浪费时间编写相同的 Mocked 方法来一遍又一遍地返回一个空列表。

这类事情有最佳实践吗?

【问题讨论】:

    标签: unit-testing ninject justmock


    【解决方案1】:

    对于类的单元测试,将 DI 容器包含在“被测系统”(SUT) 中没有多大意义。

    • 原则上,类单元测试应该只测试类和类
    • 通常您不能在单元测试中“重用”绑定,您必须针对单元测试创​​建它们。因此,您只是在重新测试 ninject,而不是在重新测试它的应用方式。 Ninject 已经过测试。所以对你没有真正的好处。

    如果您在组件或应用程序级别进行验收测试/单元测试,那么将 Ninject 包含在 SUT 中非常有意义。

    对于类级单元测试,通常采用基于动态代理的模拟框架,例如 MOQFakeItEasy

    给定一个实现:

    public interface IDependency {
        void Foo(string bar); 
    }
    
    public class SomeClass
    {
        private readonly IDependency dependency;
    
        public SomeClass(IDependency dependency)
        {
            this.dependency = dependency;
        } 
    
        public void SomeMethod(string arg)
        {
            this.dependency.Foo(arg);
        }
    }
    

    测试看起来像(xUnit 风格):

    public class SomeClassTest
    {
        private readonly Mock<IDependency> dependency;
    
        private SomeClass testee;
    
        public SomeClassTest()
        {
            this.dependency = new Mock<IDependency>();
    
            this.testee = new SomeClass(this.dependency.Object);
        }
    
        [Fact]
        public void SomeMethod_MustPassArgumentToFoo()
        {
            const string expectedArgument = "AnyArgument;
    
            this.testee.SomeMethod(expectedArgument);
    
            this.dependency.Verify(x => x.Foo(expectedArgument));
        }
    }
    

    【讨论】:

    • 我们没有像 BatteryBackupUnit 的答案那样在单元测试中使用 Ninject(顺便说一句:-),但我们在验收测试中使用它。验收测试测试(几乎)完整的功能(没有 UI、数据库或任何其他流程外部 API)。
    • @Urs 感谢您对验收测试的解释。我已将文本更改为提及“验收测试”而不是“规范测试”,因为它更广为人知且定义更精确。
    【解决方案2】:

    JustMock 内置了 NInject 以及 mocking container based on it

    当您第一次获取实例时,会自动注入依赖项的模拟:

    var container = new MockingContainer<ClassUnderTest>();
    var testee = container.Instance;
    

    另外,您可以使用 NInject 的语法对注入行为进行细粒度控制,也可以使用 JustMock 的语法来配置模拟行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 1970-01-01
      • 2012-05-03
      相关资源
      最近更新 更多