.NET Core TDD 前传: 编写易于测试的代码 -- 全局状态
第1篇: 讲述了如何创造"缝".? "缝"(seam)是需要知道的概念. 第2篇,?避免在构建对象时写出不易测试的代码. 第3篇,依赖项和迪米特法则. 本文是第4篇,将介绍全局状态引起的问题. ? 全局状态全局状态,也可以叫做应用程序状态,它是一组变量,这些变量维护着应用程序的高级状态. 在程序里,全局状态可能都存放在一个全局状态对象里,例如ASP.NET里面的HttpContext; 或者它们可能是全局的变量,这些全局变量在程序的任何地方都可以访问. 不管是如何实现的全局状态,每个全局状态变量在内存里只有一个实例. 所以如果一个类里更新了全局变量的值,那么另一个类访问该变量的时候它的值就是刚才被更新的值. 有些情况下,使用全局状态确实有用; 但是如果使用不当,则会对测试造成很大的影响. ? 全局状态对测试引起的问题
? 危险信号
? 解决办法
? 例子就举一个例子吧. 有这样一个获取当前登录用户权限的类,它使用的是单例模式: 这个是典型的单例模式,它会保证在程序中只返回一个实例,这里就不多介绍了. ? 下面这个Service会调用上面这个Auth类: Auth是单例模式的,而且还调用了静态方法. 现在的状态是,OfficeService和Auth所包含的全局状态紧密的耦合到了一起.? ? 如何解决问题首先应该把单例模式去掉,Auth类只保留两个属性和一个方法: ? 然后在service里面应该注入IAuth接口并使用: ? 那么接下来就需要保证这个IAuth无论在程序中注入了多少次,都是同一个实例. 这时就需要使用依赖注入(DI) 库了. 现在的DI库通常允许指定IoC容器中每对绑定服务的作用范围(Scope),或叫做生命周期管理. 例如ASP.NET Core内置的IoC容器就内置了这种功能. 在ASP.NET Core 项目的Startup类里,这样写就可以保证每次请求IAuth的时候只会得到同一个对象实例: 现在这个"单例"的工作是由IoC容器来负责了. 在其它地方正常的注入IAuth使用即可. ? 先写到这,本文的概念性内容和更多的例子请参考Angular创始的人这篇文章:?http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |