存根类 测试代码 java_为旧版代码创建存根-测试技术6
存根類 測試代碼 java
任何閱讀此博客的人都可能已經意識到,目前我正在開發一個項目,其中包含大量的舊代碼,這些舊代碼龐大,擴展且編寫時從未進行過任何測試。在使用此遺留代碼時,有一個行為非常差的類非常普遍,整個團隊都在不時地跳閘。
為了保護這一罪惡,我將其稱為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 id="propman" class="com.captaindebug.siteproperties.SitePropertiesManager" />我們還需要使用限定符更新AddressService的 @Autowired批注:
@Autowired@Qualifier("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
存根類 測試代碼 java
總結
以上是生活随笔為你收集整理的存根类 测试代码 java_为旧版代码创建存根-测试技术6的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 9个最佳海滩标志设计"如何免费获得[20
- 下一篇: Hostinger vs DonWeb—