6.3 替換web服務(wù)器資源
現(xiàn)在你知道如何簡(jiǎn)單地啟動(dòng)和配置Jetty了,下一步我們把視線放在HTTP連接的testcase上,你會(huì)先寫(xiě)一個(gè)測(cè)試來(lái)證明可以調(diào)用一個(gè)有效的URL,并能取得它的內(nèi)容。
6.3.1 建立第一個(gè)stub測(cè)試
為了證明webClient工作于有效的URL,你需要在測(cè)試前啟動(dòng)Jetty服務(wù)器,這些你能在Junit test case里setUp方法中實(shí)現(xiàn)。你還可以用tearDown方法停止服務(wù)器的運(yùn)行。代碼6.3列出了具體做法。
為了實(shí)現(xiàn)setUp和rearDown方法,你有兩條解決之道。準(zhǔn)備一個(gè)包含文本“it works”的靜態(tài)頁(yè)面。把該文本放在你的文檔根目錄中。另一種方法是,配置Jetty以使用你自己定制的處理器,它不用在文件系統(tǒng)的文件中取字符串,而是直接返回一個(gè)字符串。這是一個(gè)更強(qiáng)大的技術(shù),即便遠(yuǎn)程http服務(wù)器在你的webclient客戶應(yīng)用程序上拋出一個(gè)錯(cuò)誤代碼的時(shí)候,你還是能對(duì)這個(gè)test case進(jìn)行單元測(cè)試。
創(chuàng)建一個(gè)Jetty處理器
代碼6.4顯示了如何創(chuàng)建一個(gè)返回“it works”的jetty處理器。
每個(gè)test suite 啟動(dòng)和停止jetty各一次
6.4 替換連接
現(xiàn)在,你替換了服務(wù)器的資源。改為http連接又會(huì)如何呢?這樣做會(huì)妨礙你有效的測(cè)試連接,但這沒(méi)有關(guān)系,這一點(diǎn)不正是你真正的目標(biāo)
。你真正感興趣的是孤立地測(cè)試代碼邏輯。在以后的階段可以用功能測(cè)試或集成測(cè)試來(lái)檢驗(yàn)連接。
當(dāng)你需要不改變代碼替換連接的時(shí)候,你會(huì)發(fā)現(xiàn)自己很幸運(yùn),因?yàn)镴DK的URL和HttpURLConnection類允許你引入自定義的協(xié)議處理器,處理任何類型的通訊協(xié)議。你可以使任何對(duì)HttpURLConnection類的調(diào)用指向你自己的測(cè)試類,這些類會(huì)返回測(cè)試中任何需要的東西。
6.4.1 創(chuàng)建自定義RUL協(xié)議處理器
為了實(shí)現(xiàn)自定義的URL協(xié)議處理器,你需要調(diào)用以下的JDK方法,并把它傳遞給自定義的URLStramHandlerFactory對(duì)象:
Java.net.setURLStreamHandlerFactory
第7章:用mock object孤立測(cè)試
孤立于其他方法和環(huán)境而單元測(cè)試每一個(gè)方法,這顯然是個(gè)值得追求的目標(biāo)。但如何實(shí)現(xiàn)呢?在第六章中你知道了stub技術(shù)是怎樣把代碼和環(huán)境隔離起來(lái)而進(jìn)行單元測(cè)試的。那么諸如隔離調(diào)用其他類的方法此類的細(xì)粒度隔離又如何呢?可行嗎?實(shí)現(xiàn)這些會(huì)不會(huì)需要付出很大的努力,從而抵消進(jìn)行測(cè)試所帶來(lái)的收益?
回答是:“可以實(shí)現(xiàn)的”這項(xiàng)技術(shù)叫做mock objects。假設(shè)你要單元測(cè)試每一個(gè)方法,mock objects策略允許你在可能的細(xì)等級(jí)上進(jìn)行單元測(cè)試,逐個(gè)方法地進(jìn)行測(cè)試。
7.1 mock objects 簡(jiǎn)介
隔離測(cè)試有著巨大的好處,如可以測(cè)試還未寫(xiě)完的代碼,另外,隔離測(cè)試能幫助團(tuán)隊(duì)單元測(cè)試代碼的一部分,而無(wú)需等待全部代碼的完成。
也許大的好處在于編寫(xiě)專門測(cè)試單一方法的代碼,免去了被測(cè)試的方法調(diào)用其他對(duì)象而帶來(lái)的副作用。小是美。編寫(xiě)小而專一的測(cè)試是有用的;小的測(cè)試容易理解,當(dāng)代碼的其他部分改變時(shí)也不會(huì)被破壞。記住,進(jìn)行成組測(cè)試的一個(gè)好處是,它給了你重構(gòu)的勇氣――單元測(cè)試像反對(duì)衰退的衛(wèi)士。如果你的測(cè)試粒度比較大,那么一旦重構(gòu)引入了一個(gè)bug,會(huì)有一系列的測(cè)試失。唤Y(jié)果是測(cè)試告訴你出現(xiàn)了一個(gè)錯(cuò)誤,但你并不知道它在哪里。
Mock objects (簡(jiǎn)稱mocks)非常適合把部分代碼邏輯的測(cè)試同其他的代碼隔離開(kāi)來(lái)。Mocks替換了測(cè)試中你的方法協(xié)作的對(duì)象,從而提供了隔離層。從這個(gè)意義來(lái)說(shuō),它跟stub類似。
7.2 體驗(yàn)mock objects ; 一個(gè)簡(jiǎn)單例子
讓我們體驗(yàn)一下第一個(gè)mock
7.3 把Mock objects 用作重構(gòu)手法
有一些人曾經(jīng)說(shuō)過(guò),單元測(cè)試應(yīng)該對(duì)測(cè)試中的代碼透明;你不應(yīng)為了簡(jiǎn)化測(cè)試而改變運(yùn)行時(shí)代碼。這是錯(cuò)誤的!單元測(cè)試是對(duì)運(yùn)行時(shí)代碼的好應(yīng)用,應(yīng)該同其他運(yùn)用同等看待。如果你的代碼不能在測(cè)試中應(yīng)用,你應(yīng)該糾正代碼。
第8章: 使用Cactus進(jìn)行容器內(nèi)測(cè)試
本章內(nèi)容
對(duì)組件進(jìn)行單元測(cè)試時(shí)用mock objects的缺點(diǎn)
介紹使用Cactus進(jìn)行容器內(nèi)測(cè)試
Cactus的工作原理
在恰當(dāng)?shù)臅r(shí)候進(jìn)行的設(shè)計(jì),讓程序要么不能運(yùn)行,一旦運(yùn)行起來(lái)是正確運(yùn)行
從本章開(kāi)始,我們將研討如何對(duì)J2EE組件進(jìn)行單元測(cè)試.對(duì)組件進(jìn)行單元測(cè)試要難于對(duì)普通Java類進(jìn)行單元測(cè)試.組件要和它們的容器打交道,而容器只有在運(yùn)行時(shí)才能提供服務(wù).Junit并沒(méi)有像其他J2EE組件那樣被設(shè)計(jì)成在容器內(nèi)執(zhí)行,那么我們?cè)撊绾螠y(cè)試組件呢?
本章介紹了一種對(duì)J2EE組件進(jìn)行單元測(cè)試的方法:容器內(nèi)單元測(cè)試,也稱作集成單元測(cè)試.更確切地說(shuō),我們講討論使用cactus框架在容器內(nèi)運(yùn)行J2EE測(cè)試的好處和壞處.我們將展示,使用第7章介紹的mock objects方法能做到什么,而這種方法無(wú)能為力時(shí)容器內(nèi)測(cè)試方法如何使得你可以編寫(xiě)集成單元測(cè)試.
8.1 對(duì)組件進(jìn)行單元測(cè)試的問(wèn)題
想象一下,你有一個(gè)web應(yīng)用程序,它使用了servlet,你希望對(duì)sampleservlet servlet的isAuthenticated 方法進(jìn)行單元測(cè)試.
為了能夠測(cè)試這個(gè)方法,你需要得到一個(gè)合法的HttpServletRequest對(duì)象.不幸的是,不可能調(diào)用new HttpServletRequest 來(lái)創(chuàng)建一個(gè)可用的請(qǐng)求.HttpServletRequest 的生命周期是由容器管理的,無(wú)法單獨(dú)使用Junit為isAuthenticated 方法編寫(xiě)測(cè)試.
定義: 組件/容器—組件是在容器內(nèi)部執(zhí)行的一段代碼.容器則是為存放在內(nèi)的組件提供有用服務(wù)的器皿.
幸運(yùn)的是,有幾種可供選擇的解決方案,我們將在后續(xù)的小節(jié)中談到這些方案.概括地說(shuō),我們將展現(xiàn)兩種核心方案:用mock objects進(jìn)行容器外測(cè)試和用Cactus進(jìn)行容器內(nèi)測(cè)試
這兩種方法的一個(gè)變體是使用stub容器,比如HttpUnit中的ServletUnit模塊.不幸的是,我們沒(méi)有找到J2EE容器的完整stub實(shí)現(xiàn).ServletUnit只實(shí)現(xiàn)了一部分Servlet規(guī)約
Mock objects和Cactus都是可行的方法.在第7章中,我們討論了mock objects這種容器外策略的優(yōu)勢(shì)和劣勢(shì).在本章中,我們將我們專注于Cactus這種容器內(nèi)策略,并展示它的相對(duì)優(yōu)勢(shì)和劣勢(shì).第9章我們將專注于對(duì)servlet進(jìn)行單元測(cè)試.在那一章中,我們將討論當(dāng)測(cè)試servlet的時(shí)候何時(shí)使用mock objects,何時(shí)使用Cactus.
8.2 用mock objects測(cè)試組件
讓我們?cè)囍胢ock objects來(lái)測(cè)試servlet,然后討論這種方法得優(yōu)勢(shì)和劣勢(shì).在第7章中,你創(chuàng)建了你自己得mock objects.幸運(yùn)的是,有好幾個(gè)框架可以自動(dòng)生成mock objects.在本章中,你將使用EasyMock(http://www.easymock.org)