【问题标题】:MSTest TestMethod Dependency InjectionMSTest TestMethod 依赖注入
【发布时间】:2022-02-23 08:29:08
【问题描述】:

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

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

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

【问题讨论】:

    标签: .net visual-studio-2010 dependency-injection mstest


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      对我来说,根据依赖注入模式编写代码并使用 IoC 框架的主要原因是为了获得可测试的代码。但是,在您的测试代码中使用 IoC 容器会得到相反的结果。从你的问题我可以看出你已经在经历这个了。

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

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

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

      这种工厂方法的外观当然取决于(不是双关语)HomeController 的依赖结构如何。

      长话短说,不要尝试像在应用程序代码中那样在测试代码中进行依赖注入。测试框架不仅使执行此操作变得非常困难,而且还意味着您必须为您的测试环境配置 IoC 框架,在这种情况下您将走向失败。不幸的是,我是根据经验说话的。

      【讨论】:

      • 我没有使用 SL 模式,幸运的是......只有构造函数注入。我想我记得在并行测试中搜索过这个确切的问题,因为我有同样的担忧,并且看到 MSBuild 默认情况下不会并行运行测试,但我可能错了。
      • 所以我应该在我的所有测试代码中复制依赖意识和生命周期配置?换句话说,假设我在容器中有一个单例组件,然后应该将其注入到某个测试所需的 5 个瞬态组件的构造函数中?我需要为该测试进行设置,该测试知道手动实例化单例的实例并将其作为单例保留以注入到我手动实例化的每个依赖组件中?如果组件更改为不是单例怎么办?我必须为此重写所有测试设置代码吗?
      • 那么测试要注入实例构造函数的组件或服务的可用性呢?如果我手动进行实例化,我会错过测试这个关键功能的机会。我认为它很关键,因为维护状态通常是编程中更微妙的部分之一,如果我不测试组件的可用性,那么我完全错过了测试状态管理的有效性,对吧?我对编程最坚定的信念之一就是 DRY。更具体地说,“不要在两个地方保持状态!”。
      • 我从未遇到过需要在测试对象中注入单例的情况。当我注入一个虚假的依赖时,我总是为每个测试创建一个新对象。因此,生活方式在您的测试中并不重要,因为它不应该适用于使用该依赖项的类。
      • 如果你有一些类作为单例注入并维护一些状态(或缓存,或其他),你可能想单独测试它。如果你在测试中使用这个带状态的单例,你会开始得到相互依赖的测试,这使得保持测试的可信度变得非常困难。然而,我想做的是在根应用程序本身(通常是 Web 应用程序或 Web 服务)上有一个测试项目,并进行一些验证 DI 配置的测试。
      猜你喜欢
      • 1970-01-01
      • 2011-04-08
      • 2014-06-12
      • 2013-04-30
      • 2021-11-19
      • 1970-01-01
      • 2020-12-20
      相关资源
      最近更新 更多