我们一直在相当大的应用程序中使用 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/