网站图片自动切换怎么做,网络推广引流方法,站内营销推广方案,伍佰亿官方网站任何阅读此博客的人都可能已经意识到#xff0c;目前我正在开发一个包含大量旧代码的项目#xff0c;这些旧代码庞大#xff0c;扩展且编写时从未进行过任何测试。 在使用此遗留代码时#xff0c;有一个行为异常的类非常普遍#xff0c;整个团队都一次又一次地犯错。 为了… 任何阅读此博客的人都可能已经意识到目前我正在开发一个包含大量旧代码的项目这些旧代码庞大扩展且编写时从未进行过任何测试。 在使用此遗留代码时有一个行为异常的类非常普遍整个团队都一次又一次地犯错。 为了保护这一罪恶我将其称为X先生尽管它的真名是SitePropertiesManager因为它管理网站的属性。 表现不佳是因为 打破单一责任主体 使用了由getInstance工厂方法汇总的单例模式 有一个init方法必须在其他任何方法之前调用它 通过直接访问数据库而不是使用DAO加载其数据 使用复杂的地图来存储其数据 访问文件系统以缓存数据库返回的数据 有一个计时器来决定何时更新其缓存。 是在泛型之前编写的具有大量多余的findXXXX方法。 没有实现接口 使用了大量的复制和粘贴程序。 这使得在编写新代码的单元测试时很难创建存根并使旧代码杂乱无章 SitePropertiesManager propman SitePropertiesManager.getInstance(); 该博客介绍了处理尴尬字符的方法并演示了如何为它们创建存根同时消除了Singleton模式的影响。 与以前的“测试技术”博客一样我的演示代码也基于“地址”网络应用示例 。 在本系列的其他博客中我一直在演示如何测试AddressService 这个博客也没有什么不同。 但是在这种情况下 AddressService必须加载站点属性并决定是否返回地址但是在查看之前我首先需要使用写得不好的SitePropertiesManager来使用。 但是我不拥有该代码因此我编写了一个特技双重版本该版本打破了我能想到的许多规则。 我不会在这里让您感到厌烦因为SitePropertiesManager的所有源代码都可以在以下位置找到git//github.com/roghughe/captaindebug.git 如上所述在这种情况下 AddressService使用站点属性来确定是否启用了它。 如果是它将发送回一个地址对象。 我还要假装AddressService是一些使用站点属性静态工厂方法的旧代码如下所示 public Address findAddress(int id) {logger.info(In Address Service with id: id);Address address Address.INVALID_ADDRESS;if (isAddressServiceEnabled()) {address addressDao.findAddress(id);address businessMethod(address);}logger.info(Leaving Address Service with id: id);return address;}private boolean isAddressServiceEnabled() {SitePropertiesManager propManager SitePropertiesManager.getInstance();return new Boolean(propManager.findProperty(address.enabled));} 在驯服这种类型的类时他要做的第一件事是停止使用getInstance获取保持和一个对象将其从上述方法中删除并开始使用依赖项注入。 必须至少调用一次getInstance 但这可以在程序的启动代码中进行。 在Spring的世界中解决方案是将行为不佳的类包装在Spring FactoryBean实现中该类成为应用程序中getInstance的唯一位置–至少对于新代码/增强代码而言。 public class SitePropertiesManagerFactoryBean implementsFactoryBean {private static SitePropertiesManager propsManager SitePropertiesManager.getInstance();Overridepublic SitePropertiesManager getObject() throws Exception {return propsManager;}Overridepublic Class getObjectType() {return SitePropertiesManager.class;}Overridepublic boolean isSingleton() {return true;}
} 现在可以将其自动连接到AddressService类中 Autowiredvoid setPropertiesManager(SitePropertiesManager propManager) {this.propManager propManager;} 但是这些更改并不意味着我们可以为AddressService编写一些适当的单元测试它们只是准备基础。 下一步是为SitePropertiesManager提取接口使用eclipse可以轻松实现。 public interface PropertiesManager {public abstract String findProperty(String propertyName);public abstract String findProperty(String propertyName, String locale);public abstract List findListProperty(String propertyName);public abstract List findListProperty(String propertyName, String locale);public abstract int findIntProperty(String propertyName);public abstract int findIntProperty(String propertyName, String locale);} 在转移到接口时我们还需要在Spring配置文件中手动配置SitePropertiesManager的实例以便Spring知道将哪个类连接到哪个接口 beans:bean idpropman classcom.captaindebug.siteproperties.SitePropertiesManager / 我们还需要使用限定符更新AddressService的 Autowired批注 AutowiredQualifier(propman)void setPropertiesManager(PropertiesManager propManager) {this.propManager propManager;} 通过一个接口我们现在可以轻松编写一个简单的SitePropertiesManager存根 public class StubPropertiesManager implements PropertiesManager {private final Map propMap new HashMap();public void setProperty(String key, String value) {propMap.put(key, value);}Overridepublic String findProperty(String propertyName) {return propMap.get(propertyName);}Overridepublic String findProperty(String propertyName, String locale) {throw new UnsupportedOperationException();}Overridepublic List findListProperty(String propertyName) {throw new UnsupportedOperationException();}Overridepublic List findListProperty(String propertyName, String locale) {throw new UnsupportedOperationException();}Overridepublic int findIntProperty(String propertyName) {throw new UnsupportedOperationException();}Overridepublic int findIntProperty(String propertyName, String locale) {throw new UnsupportedOperationException();}
} 有了存根很容易为使用存根并与数据库和文件系统隔离的AddressService编写单元测试 public class AddressServiceUnitTest {private StubAddressDao addressDao;private StubPropertiesManager stubProperties;private AddressService instance;Beforepublic void setUp() {instance new AddressService();stubProperties new StubPropertiesManager();instance.setPropertiesManager(stubProperties);}Testpublic void testAddressSiteProperties_AddressServiceDisabled() {/* Set up the AddressDAO Stubb for this test */Address address new Address(1, 15 My Street, My Town, POSTCODE,My Country);addressDao new StubAddressDao(address);instance.setAddressDao(addressDao);stubProperties.setProperty(address.enabled, false);Address expected Address.INVALID_ADDRESS;Address result instance.findAddress(1);assertEquals(expected, result);}Testpublic void testAddressSiteProperties_AddressServiceEnabled() {/* Set up the AddressDAO Stubb for this test */Address address new Address(1, 15 My Street, My Town, POSTCODE,My Country);addressDao new StubAddressDao(address);instance.setAddressDao(addressDao);stubProperties.setProperty(address.enabled, true);Address result instance.findAddress(1);assertEquals(address, result);}
} 所有这些都是很笨拙的但是如果您不能提取接口会发生什么呢 我将其保存另一天... 参考 Captain Debug博客上的 JCG合作伙伴 Roger Hughes提供的用于遗留代码的存根-测试技术6 相关文章 测试技巧–不编写测试 端到端测试的滥用–测试技术2 您应该对什么进行单元测试 –测试技术3 常规单元测试和存根–测试技术4 使用模拟的单元测试–测试技术5 有关为旧版代码创建存根的更多信息–测试技术7 为什么要编写单元测试–测试技巧8 一些定义–测试技术9 使用FindBugs产生更少的错误代码 在云中开发和测试 翻译自: https://www.javacodegeeks.com/2011/11/creating-stubs-for-legacy-code-testing.html