![測(cè)試對(duì)象串行化_第1頁](http://file4.renrendoc.com/view/cd2d092c9b8dd9a602d46ba5aeebbeb6/cd2d092c9b8dd9a602d46ba5aeebbeb61.gif)
![測(cè)試對(duì)象串行化_第2頁](http://file4.renrendoc.com/view/cd2d092c9b8dd9a602d46ba5aeebbeb6/cd2d092c9b8dd9a602d46ba5aeebbeb62.gif)
![測(cè)試對(duì)象串行化_第3頁](http://file4.renrendoc.com/view/cd2d092c9b8dd9a602d46ba5aeebbeb6/cd2d092c9b8dd9a602d46ba5aeebbeb63.gif)
![測(cè)試對(duì)象串行化_第4頁](http://file4.renrendoc.com/view/cd2d092c9b8dd9a602d46ba5aeebbeb6/cd2d092c9b8dd9a602d46ba5aeebbeb64.gif)
![測(cè)試對(duì)象串行化_第5頁](http://file4.renrendoc.com/view/cd2d092c9b8dd9a602d46ba5aeebbeb6/cd2d092c9b8dd9a602d46ba5aeebbeb65.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第第頁測(cè)試對(duì)象串行化測(cè)試對(duì)象串行化
發(fā)表于:2023-05-24來源::點(diǎn)擊數(shù):標(biāo)簽:開發(fā)測(cè)試使最杰出串行
即使最杰出的開發(fā)人員有時(shí)也會(huì)忘記測(cè)試對(duì)象串行化,但那并不能作為您犯下同一錯(cuò)誤的借口。在這篇文章中,ElliotteRustyHarold將解釋對(duì)對(duì)象串行化進(jìn)行單元測(cè)試的重要性,并為您展示一些應(yīng)牢記的測(cè)試。測(cè)試驅(qū)動(dòng)的開發(fā)的總體原則之一就是應(yīng)測(cè)試一個(gè)類已
即使最杰出的開發(fā)人員有時(shí)也會(huì)忘記(測(cè)試)對(duì)象串行化,但那并不能作為您犯下同一錯(cuò)誤的借口。在這篇文章中,ElliotteRustyHarold將解釋對(duì)對(duì)象串行化進(jìn)行單元測(cè)試的重要性,并為您展示一些應(yīng)牢記的測(cè)試。測(cè)試驅(qū)動(dòng)的(開發(fā))的總體原則之一就是應(yīng)測(cè)試一個(gè)類已發(fā)布的所有接口。如果客戶機(jī)能夠調(diào)用方法或訪問字段,那么就測(cè)試它。但在(Java)語言中,許多類都有一個(gè)已發(fā)布的接口容易被遺漏:通過類實(shí)例生成的串行化對(duì)象。有時(shí)這些類顯式實(shí)現(xiàn)Serializable。而有時(shí)則是直接從超類繼承這一特性。在任何一種情況下,您都應(yīng)該測(cè)試其串行化形式。本文將介紹幾種測(cè)試對(duì)象串行化的方法。
測(cè)試串行化
對(duì)串行化來說,測(cè)試極其重要,因?yàn)榇谢浅7浅H菀壮鲥e(cuò)。在修復(fù)(bug)或優(yōu)化類時(shí),非常容易破壞所有已有串行化對(duì)象。如果您在更改代碼時(shí)未考慮串行化,幾乎可以肯定您必將破壞原有對(duì)象。若您正在為任何形式的持久性存儲(chǔ)使用串行化,那么這將是一個(gè)嚴(yán)重的(bug)。即便僅為流程間的瞬時(shí)消息傳遞(如在RMI中)使用對(duì)象串行化,更改串行化格式也會(huì)使那些各類的版本不完全相同的系統(tǒng)無法順利交換數(shù)據(jù)。
告訴每一個(gè)人。將此提交到:
DiggSlashdot
幸運(yùn)的是,若您謹(jǐn)慎對(duì)待串行化問題,在處理類時(shí)通常可以避免不兼容的更改。Java語言提供了多種方法,可維護(hù)一個(gè)類的不同版本之間的(兼容性),包括:
serialVersionUIDtransient修飾符readObject()和writeObject()writeReplace()和readResolve()serialPersistentFields對(duì)于這些解決方案來說,最大的問題就在于程序員未使用它們。當(dāng)您將精力集中在修復(fù)bug、添加特性或解決性能問題時(shí),往往不會(huì)停下來思考您的更改對(duì)串行化造成的影響。然而串行化是一個(gè)涉及范圍極廣的問題跨越一個(gè)系統(tǒng)的多個(gè)不同層。幾乎所有更改都會(huì)涉及對(duì)串行化有某種影響的一個(gè)類的實(shí)例字段。這正是(單元測(cè)試)發(fā)揮作用的時(shí)機(jī)。在本文后續(xù)各節(jié)中,我將為您展示一些簡單的(單元測(cè)試),這些單元測(cè)試能確保您不會(huì)不經(jīng)意地更改可串行化類的串行格式。
回頁首
我能否將其串行化?
通常您編寫的第一個(gè)串行化測(cè)試就是用于驗(yàn)證串行化是否可行的測(cè)試。即使一個(gè)類實(shí)現(xiàn)了Serializable,依然不能保證它能夠串行化。例如,如果一個(gè)可串行化的容器(如ArrayList)包含一個(gè)不可串行化的對(duì)象(如Socket),則在您嘗試串行化此容器時(shí),將拋出NotSerializableException。
通常,對(duì)此測(cè)試,您只需在ByteArrayOutputStream上寫入數(shù)據(jù)。若未拋出任何異常,測(cè)試即通過。如果您愿意,還可測(cè)試一些已寫入的輸出。例如,清單1所示代碼片段用于測(cè)試Jaxen的BaseXPath類是否可串行化:
清單1.此類是否可串行化?
publicvoidtestIsSerializable()throwsJaxenException,IOException{BaseXPathpath=newBaseXPath(//foo,newDocumentNavigator());ByteArrayOutputStreamout=newByteArrayOutputStream();ObjectOutputStreamoos=newObjectOutputStream(out);oos.writeObject(path);oos.close();assertTrue(out.toByteArray().length0);}
回頁首
測(cè)試串行化形式
接下來,您想要編寫一個(gè)測(cè)試,不僅要驗(yàn)證輸出得到了顯示,還要驗(yàn)證輸出是正確的。您可通過兩種方式完成這一任務(wù):
反串行化對(duì)象,并將其與原始對(duì)象相比較。逐字節(jié)地將其與參考.ser文件相比較。我通常會(huì)從第一種選擇入手,因?yàn)樗€提供了一個(gè)反串行化的簡單測(cè)試,而且編碼和實(shí)現(xiàn)相對(duì)來說比較容易。例如,清單2所示代碼片段將測(cè)試Jaxen的SimpleVariableContext類是否可寫入并在之后重新讀回:
清單2.反串行化對(duì)象,并將其與原始對(duì)象相比較
publicvoidtestRoundTripSerialization()throwsIOException,ClassNotFoundException,UnresolvableException{//constructtestobjectSimpleVariableContextoriginal=newSimpleVariableContext();original.setVariableValue(s,StringValue);original.setVariableValue(x,newDouble(3.1415292));original.setVariableValue(b,Boolean.TRUE);//serializeByteArrayOutputStreamout=newByteArrayOutputStream();ObjectOutputStreamoos=newObjectOutputStream(out);oos.writeObject(original);oos.close();//deserializebyte[]pickled=out.toByteArray();InputStreamin=newByteArrayInputStream(pickled);ObjectInputStreamois=newObjectInputStream(in);Objecto=ois.readObject();SimpleVariableContextcopy=(SimpleVariableContext)o;//testtheresultassertEquals(StringValue,copy.getVariableValue(,,s));assertEquals(Double.valueOf(3.1415292),copy.getVariableValue(,,x));assertEquals(Boolean.TRUE,copy.getVariableValue(,,b));assertEquals(,);}
讓我們?cè)僭囈淮?/p>
在測(cè)試代碼基礎(chǔ)中那些此前從未測(cè)試過的部分時(shí),幾乎總是會(huì)發(fā)現(xiàn)bug,對(duì)象串行化也是這樣。在我第一次運(yùn)行清單2中的測(cè)試時(shí),測(cè)試失敗了,輸出結(jié)果如清單3所示:
清單3.不可串行化
(java).io.NotSerializableException:org.jaxen.QualifiedNameat(java).io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1075)atjava.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)atjava.util.HashMap.writeObject(HashMap.java:984)atsun.reflect.NativeMethodAclearcase/"target="_blank">ccessorImpl.invoke0(NativeMethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)atjava.lang.reflect.Method.invoke(Method.java:585)atjava.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:890)atjava.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1333)atjava.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1284)atjava.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)atjava.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1369)atjava.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1341)atjava.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1284)atjava.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1073)atjava.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)atorg.jaxen.test.SimpleVariableContextTest.testRoundTripSerialization(SimpleVariableContextTest.java:90)
這表明,SimpleVariableContext包含一個(gè)對(duì)QualifiedName對(duì)象的引用,QualifiedName類未標(biāo)記為Serializable。我為QualifiedName的類簽名添加了implementsSerializable,這一次測(cè)試順利通過。
注意,此測(cè)試實(shí)際上并未驗(yàn)證串行化格式是否正確只是驗(yàn)證出對(duì)象能夠來回轉(zhuǎn)換。為測(cè)試正確性,您需要生成一些參考文件,以便與類的所有未來版本的輸出相比較。
回頁首
測(cè)試反串行化
通常,您不能依賴默認(rèn)串行化格式來保持類的不同版本間的文件格式兼容性。您必須使用serialPersistentFields、readObject()和writeObject()方法和/或transient修飾符,通過各種方式進(jìn)行定制。如果您確實(shí)對(duì)類的串行化格式做出了不兼容的更改,應(yīng)相應(yīng)更改serialVersionUID字段,以指出您這樣做了。
正常情況下,您不會(huì)過分關(guān)注串行化對(duì)象的詳細(xì)結(jié)構(gòu)。而只是關(guān)注最初使用的那種格式隨著類的發(fā)展得到了維護(hù)。一旦類基本上具備了恰當(dāng)?shù)男问?,即可寫入一些類的串行化?shí)例,并存儲(chǔ)在隨后可將其作為參考使用的位置處。(您很可能確實(shí)希望多多少少地考慮如何串行化才能確保足夠的靈活性,以便應(yīng)對(duì)未來的發(fā)展。)
編寫串行化實(shí)例的程序是臨時(shí)代碼,只需使用一次。實(shí)際上,您根本就不應(yīng)該多次運(yùn)行這段代碼,因?yàn)槟幌M@得串行化格式中的任何意外更改。例如,清單4展示了用于串行化Jaxen的SimpleVariableContext類的程序:
清單4.寫入串行化實(shí)例的程序
importorg.jaxen.*;importjava.io.*;publicclassMakeSerFiles{publicstaticvoidmain(String[]args)throwsIOException{OutputStreamfout=newFileOutputStream(xml/simplevariablecontext.ser);ObjectOutputStreamout=newObjectOutputStream(fout);SimpleVariableContextcontext=newSimpleVariableContext();context.setVariableValue(s,StringValue);context.setVariableValue(x,newDouble(3.1415292));context.setVariableValue(b,Boolean.TRUE);out.writeObject(context);out.flush();out.close();}}
您只需將一個(gè)串行化對(duì)象寫入文件而且只需一次。這是您希望保存的文件,而不是用于寫入的代碼。清單5展示了Jaxen的SimpleVariableContext類的兼容性測(cè)試:
清單5.確保文件格式未被更改
publicvoidtestSerializationFormatHasNotChanged()throwsIOException,ClassNotFoundException,UnresolvableException{//deserializeInputStreamin=newFileInputStream(xml/simplevariablecontext.ser);ObjectInputStreamois=newObjectInputStream(in);Objecto=ois.readObject();SimpleVariableContextcontext=(SimpleVariableContext)o;//testtheresultassertEquals(StringValue,context.getVariableValue(,,s));assertEquals(Double.valueOf(3.1415292),context.getVariableValue(,,x));assertEquals(Boolean.TRUE,context.getVariableValue(,,b));assertEquals(,);}
回頁首
測(cè)試不可串行性
默認(rèn)情況下,類通常是可串行化的。例如,java.lang.Throwable或java.awt.Component的任何子類都會(huì)從其祖先繼承可串行性。在某些情況下,這也是您希望的結(jié)果,但并非總是如此。有的時(shí)候,串行化可能會(huì)成為安全漏洞,使惡意程序員能夠在不調(diào)用構(gòu)造函數(shù)或setter方法的情況下創(chuàng)建對(duì)象,從而規(guī)避了您小心翼翼地在類中構(gòu)建的所有約束性檢查。
若您希望類可串行化,就需要測(cè)試它,這與您需要測(cè)試一個(gè)直接實(shí)現(xiàn)了Serializable的類相同。如果您不希望類可串行化,則應(yīng)重寫writeObject()和readObject(),使兩者均拋出NotSerializableException,隨后您也需要對(duì)其進(jìn)行測(cè)試。
此類測(cè)試的實(shí)現(xiàn)方法與其他任何JUnit異常測(cè)試相似。只需在應(yīng)拋出異常的語句兩端包圍一個(gè)try塊即可,隨后緊接欲拋出異常的語句之后添加一條fail()語句。如果愿意,您還可在catch中作出一些關(guān)于所拋出異常的斷言。例如,清單6驗(yàn)證了FunctionContext是不可串行化的:
清單6.測(cè)試FunctionContext是不可串行化的
publicvoidtestSerializeFunctionContext()throwsJaxenException,IOException{DOMXPathxpath=newDOMXPath(/root/child);FunctionContextcontext=xpath.getFunctionContext();ByteArrayOutputStreamout=newByteArrayOutputStream();ObjectOutputStreamoout=newObjectOutputStream(out);try{oout.writeObject(context);fail(serializedfunctioncontext);}catch(NotSerializableExceptionex){assertNotNull(ex.getMessage());}
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度互聯(lián)網(wǎng)數(shù)據(jù)中心托管服務(wù)合同
- 2025年度企業(yè)定制化出租車租賃服務(wù)合同
- 2025年度養(yǎng)老機(jī)構(gòu)護(hù)理科室承包服務(wù)合同
- 喝酒處分撤銷申請(qǐng)書
- 2025年度建筑勞務(wù)市場(chǎng)信息服務(wù)平臺(tái)合作合同
- 個(gè)人銀行申請(qǐng)書
- 2025年度文化遺址保護(hù)與修復(fù)工程合同范本
- 2025年度智能音響系統(tǒng)定制安裝服務(wù)合同范本
- 2025年度建筑工程安全監(jiān)理合同
- 技術(shù)人員的申請(qǐng)書
- 礦井地質(zhì)學(xué)全套課件完整版ppt教程(最新)
- 精密配電列頭柜介紹講義
- 技能大師工作室建設(shè)PPT幻燈片課件(PPT 66頁)
- 廣東部分地區(qū)的暴雨強(qiáng)度公式
- 鋼琴基礎(chǔ)教程1教案
- 上??萍及妫瓢妫┏踔袛?shù)學(xué)八年級(jí)下冊(cè)全冊(cè)教案
- 裝修工程竣工驗(yàn)收?qǐng)?bào)告模板
- 泥水盾構(gòu)簡介
- 簡單娛樂yy頻道設(shè)計(jì)模板
- 防止機(jī)組非計(jì)劃停運(yùn)措施(鍋爐專業(yè))
- 最常用漢字個(gè)
評(píng)論
0/150
提交評(píng)論