接口與單元測(cè)試隨想
剛才看到一則關(guān)于TDD的新聞,挺雷的......然后又想起以前跟別人解釋關(guān)于為什么在Spring里需要先寫(xiě)個(gè)接口XXXInterface,然后再寫(xiě)實(shí)現(xiàn)類(lèi)XXXInterfaceImpl的問(wèn)題。寫(xiě)一點(diǎn)自己的想法,關(guān)于單元測(cè)試。
一個(gè)情景:
一個(gè)User類(lèi),提供一個(gè)靜態(tài)方法:(這里不討論框架或者異常控制流程的正確性)
public class User{ public static User login(String username,String password) throw LoginException{ |
下面討論如何對(duì)這個(gè)方法進(jìn)行測(cè)試:
單純對(duì)于這個(gè)模塊進(jìn)行單元測(cè)試:
public class UserTest{ public void testLogin(){ |
這樣的測(cè)試,正確性和速度實(shí)際上都保證不了。因?yàn)閘ogin中引入了數(shù)據(jù)庫(kù)的各種操作,各種未知的可能性都是存在的。比如說(shuō)數(shù)據(jù)庫(kù)并未配置正確或者數(shù)據(jù)庫(kù)當(dāng)前無(wú)法訪(fǎng)問(wèn),直接會(huì)導(dǎo)致這個(gè)測(cè)試失敗,但測(cè)試失敗并不意味著User.login方法錯(cuò)了。同時(shí),由于訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)造成的速度可能使這么一個(gè)簡(jiǎn)單的測(cè)試需要幾百毫秒甚至幾秒,那么大量的測(cè)試用例加在一起,如文中提到的花費(fèi)個(gè)幾十分鐘是絕對(duì)可能的。
實(shí)際上這個(gè)簡(jiǎn)單的測(cè)試方案違背了單元測(cè)試的基本原則:?jiǎn)卧獪y(cè)試應(yīng)該測(cè)試獨(dú)立的單元模塊,這個(gè)單元不應(yīng)依賴(lài)于其他模塊。在這里顯然這個(gè)Login的方法使用DAO中的一些方法。
下面討論DAO:
public class UserDAO implements DAO<User>{ public class DAOFactory{ public static DAOFactory getInstance(){ |
一般來(lái)說(shuō)DAO部分都跟上面的差不多(或許是直接注入進(jìn)User的,但實(shí)際原理是一致的):一共兩個(gè)步驟:1、獲取DAO;2、使用DAO。為了不讓User的測(cè)試受到DAO部分的干擾,就需要使用Mock技術(shù),對(duì)DAO對(duì)象進(jìn)行模擬,保證其各種方法的正確性。然后當(dāng)User類(lèi)需要獲取DAO時(shí),將MockUserDAO代替UserDAO交給它。
public class MockUserDAO implements DAO<User>{ //肯定準(zhǔn)確的實(shí)現(xiàn) } |
而DAOFactory由于是單例,其方法getInstance是靜態(tài)的,所以最后只能靠修改原始代碼來(lái)實(shí)現(xiàn)獲得另一個(gè)工廠(chǎng)——也就是MockDAOFactory。如果在程序員和單元測(cè)試人員不是同一個(gè)人的時(shí)候,真的是非常麻煩的事情..... (從這個(gè)角度上將,我極力反對(duì)靜態(tài)方法)雖說(shuō)這種情形可以靠反射來(lái)進(jìn)行偽造實(shí)例的活動(dòng),但是這種解決方案總是有一種黑客的感覺(jué)....
另外就是如果DAO不是接口,而只有實(shí)現(xiàn)(這并不是不可能的情況,在有通用DAO的前提下,完全可以達(dá)到),情況也會(huì)很麻煩。由于DAO不是接口,導(dǎo)致無(wú)法Mock這個(gè)DAO。也許可以使用MockDAO extends DAO的方案,但也許在DAO的構(gòu)造方法中依舊有著連接數(shù)據(jù)庫(kù),初始化連接池,初始化日志等等的初始化過(guò)程,由于其在構(gòu)造方法中,是無(wú)法覆蓋掉的。在這種情況下,就只能通過(guò)重構(gòu)來(lái)實(shí)現(xiàn)測(cè)試了。(這也就是即使只有一個(gè)實(shí)現(xiàn),也要盡量寫(xiě)一個(gè)接口的原因)
單元測(cè)試是至關(guān)重要的,我個(gè)人認(rèn)為,如果一個(gè)團(tuán)隊(duì)中的程序員頭腦都不錯(cuò),那么包括getter和setter都應(yīng)該測(cè)試。單元測(cè)試的度基本上可以說(shuō)是寧濫勿缺的。
挺雜亂的,不過(guò)只是隨想,所以也無(wú)所謂。
原文鏈接:http://my.oschina.net/Jeky/blog/30354
posted on 2013-05-08 10:34 順其自然EVO 閱讀(562) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): 敏捷測(cè)試