MSTest TestMethod依赖注入

Jef*_*eff 6 .net mstest dependency-injection visual-studio-2010

我正在使用DI容器,我想用容器中解析的实例进行MSTest(VS 2010)单元测试.

我想将这些实例注入我的TestMethod或至少我的TestClass.这可能吗?

现在我的TestMethods直接调用container.Resolve<T>(xxx)我宁愿避免的,这样我的注射测试更加真实.

有人有这方面的经验吗?

提前致谢.

Dar*_*rov 6

测试类的实例化深入地发生在MSTest框架的内部类中,因此将依赖项注入其中将是一项具有挑战性的任务.


Ste*_*ven 5

根据依赖注入模式和使用IoC框架编写代码的主要原因是获得可测试的代码.但是,在测试代码中使用IoC容器会得到相反的结果.从你的问题我可以看出你已经体验到了这一点.

使用服务定位器(SL)模式而不是依赖注入(DI)模式时尤其如此.使用SL模式,类直接调用IoC容器(或此类容器的抽象),而不是为类提供所需的依赖项(使用构造函数注入).由于类直接调用容器,因此您还需要在测试环境中配置该容器.这很痛苦,因为测试配置或假对象通常变得非常复杂,因为您经常希望在每个测试的基础上影​​响假的行为,同时保持线程安全,因为测试框架可能并行运行您的测试( MSTest这样做).我知道我在过去写了一些疯狂的线程安全测试代码,然后才发现我做错了:-(.

因此,您应该在应用程序代码中使用DI模式,并且在测试中,您应该手动连接这些依赖项.例如,当对HomeController依赖于ICustomerService类的类进行测试时,通常应该在测试类中使用CreateController()或者CreateValidController工厂方法来集中创建它HomeController.这样可以避免在每次测试中编写这些依赖项,从而在测试代码中创建维护噩梦.在这个工厂方法中,您FakeCustomerService通过执行以下操作手动注入一个类:

private static HomeController CreateController(
    InMemoryDataMapper mapper)
{
    var uowFactory = new FakeNorthwindUnitOfWorkFactory()
    {
        UnitOfWork = new NorthwindUnitOfWork(mapper);
    };

    return new HomeController(new FakeCustomerService(uowFactory));
}
Run Code Online (Sandbox Code Playgroud)

当然,这样的工厂方法看起来如何依赖于(没有双关语意图)依赖结构的HomeController外观.

简而言之,不要尝试在测试代码中执行依赖注入,就像在应用程序代码中一样.测试框架不仅难以实现这一点,而且还意味着您必须为测试环境配置IoC框架,在这种情况下,您将面临失败.不幸的是,我从经验谈起.

  • 所以我应该在我所有的测试代码中复制依赖感知和生命周期配置?换句话说,假设我在容器中有一个单例组件,然后应该将其注入到某个测试所需的 5 个瞬态组件的构造函数中?我需要为该测试进行设置,该测试知道手动实例化单例的实例并将其作为单例保留以注入到我手动实例化的每个依赖组件中?如果组件变为非单例怎么办?我必须为此重写我所有的测试设置代码吗? (3认同)
  • 如果您有一些作为单例注入并维护某种状态(或缓存,或其他什么)的类,您可能需要单独测试它。如果您在测试中使用带有状态的单例,您将开始获得相互依赖的测试,这使得保持测试的可信度变得非常困难。然而,我想做的是在根应用程序本身(通常是 Web 应用程序或 Web 服务)上进行一个测试项目,并进行一些验证 DI 配置的测试。 (2认同)