c# - 在单元测试中使用 DI 容器

标签 c# unit-testing dependency-injection ioc-container simple-injector

我们一直在相当大的应用程序中使用 Simple Injector 并取得了成功。我们一直在为所有生产类使用构造函数注入(inject),并配置 Simple Injector 来填充所有内容,一切都很顺利。

不过,我们还没有使用 Simple Injector 来管理单元测试的依赖树。相反,我们一直在手动更新所有内容。

我刚刚花了几天时间进行重大重构,几乎所有时间都花在了修复单元测试中这些手动构建的依赖树上。

这让我想知道 - 有没有人有任何模式来配置他们在单元测试中使用的依赖树?至少对我们来说,在我们的测试中,我们的依赖树往往相当简单,但它们有很多。

谁有管理这些的方法?

最佳答案

对于真正的单元测试(即只测试一个类并模拟其所有依赖项的单元测试),使用 DI 框架没有任何意义。在这些测试中:

  • 如果您发现您有很多重复代码来新建您的类实例以及您创建的所有模拟,一个有用的策略是创建所有模拟并在您的 Setup 方法中为被测对象创建实例(这些都可以是私有(private)实例字段),然后每个单独测试的“安排”区域只需调用适当的 Setup() 代码关于它需要模拟的方法。这样,您最终每个测试类只有一个 new PersonController(...) 语句。
  • 如果您需要创建大量域/数据对象,创建以合理值开头的 Builder 对象用于测试会很有用。因此,您不是在整个代码中调用一个巨大的构造函数,而是使用一堆假值,您主要只是调用,例如,var person = new PersonBuilder().Build(),可能只是一些链式方法调用您在该测试中特别关心的数据片段。您可能还对 AutoFixture 感兴趣,但我从未使用过它,所以我不能保证。

如果您正在编写集成测试,您需要测试系统多个部分之间的交互,但您仍然需要能够模拟特定部分,请考虑为您的创建 Builder 类服务,所以你可以说,例如var personController = new PersonControllerBuilder.WithRealDatabase(connection).WithAuthorization(new AllowAllAuthorizationService()).Build()

如果您正在编写端到端或“场景”测试,您需要在其中测试整个系统,那么设置您的 DI 框架是有意义的,利用您的实际产品使用的相同配置代码.您可以稍微更改配置,以便更好地以编程方式控制用户登录等。您仍然可以利用您创建的其他构建器类来构建数据。

var user = new PersonBuilder().Build();
using(Login.As(user))
{
     var controller = Container.Get<PersonController>();
     var result = controller.GetCurrentUser();
     Assert.AreEqual(result.Username, user.Username)
}

关于c# - 在单元测试中使用 DI 容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32594803/

相关文章:

unit-testing - 如何对pubsub进行单元测试接收回调

javascript - 语法错误 : Unexpected token : when running jest test with Aurelia in TypeScript

c# - 控制反转如何帮助我?

python - 设计模式名称 : get class from class level

c# - 在 C# 中将 var 作为方法参数传递

c# - 速度 - 将位图数据复制到数组中还是直接使用它?

c# - 集中显示应用程序名称

c# - 客户端证书不是由 .Net App 使用 TLS1.2 发送的

eclipse - 模拟 eclipse SWT/JFACE 对话框和小部件

c# - 使用静态工厂是依赖注入(inject)的有效模式吗?