在我的探查器报告中,我越来越多地看到使用依赖项注入进行基于模拟的测试的结果。许多依赖项是静态的,但因为我们想要单独测试方法,所以它们被更改为实例成员,如下例所示:
class ShortLivedThing {
IDependency1 dep1;
IDependency1 dep2;
IDependency1 dep3;
...
int TheRealData;
// Constructor used in production
public ShortLivedThing() {
dep1 = new Dep1(); dep2 = new Dep2(); dep3 = new Dep3();
}
// DI for testing
public ShortLivedThing(IDependency1 d1, IDependency2 d2, IDependency3 d3) {
dep1 = d1(); dep2 = d2(); dep3 = d3();
}
}
反过来,大多数时候,依赖关系还有其他依赖关系,依此类推。这导致实例化一棵(大部分是“静态”)对象树每次方法调用是在测试之外完成的。每个对象都非常小(只有几个指针),但树效应将其转化为不断增加的性能损失。
我们对于它可以做些什么呢?
在我看来,您需要利用适当的依赖注入框架可以提供的功能。不要使用不同的构造逻辑进行测试/生产。
使用 Spring,单例注入仅在容器启动时执行。每次都会进行原型注射。每次运行单元测试时也会完成完整的接线(如果已接线)。因此分析单元测试通常不是一个好主意。
也许您使用的单例作用域太少而原型作用域太多? (原型=每次都有新实例)
spring 注入的好处是您可以使用作用域代理,这意味着您的对象图可以如下所示:
A Singleton
|
B Singleton
|
C Prototype (per-invocation)
|
D Singleton
|
E Session scope (web app)
|
F Singleton
每个请求在每个会话中只会创建 1 个 C 实例和 1 个 E 实例。 A、B、D 和 F 是单例。如果它不是 Web 应用程序,则默认情况下没有会话作用域,但您也可以创建自定义作用域(“窗口”作用域对于窗口桌面应用程序来说听起来很酷)。这里的线索是,您可以在任何级别“引入”作用域,实际上您可以拥有十层单例对象,并且突然出现一些会话作用域的内容。 (这确实可以彻底改变您在分层架构中实现一些横切功能的方式,但这是一个不同的故事)
我认为,这确实在 DI 模型中提供了尽可能少的对象创建。
虽然这是 Spring for Java,但我相信许多其他 DI 框架应该支持类似的功能。也许不是最简约的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)