專利名稱:測試邏輯與服務(wù)器端對象的松耦合式測試方法和系統(tǒng)的制作方法
技術(shù)領(lǐng)域:
本發(fā)明涉及計算機領(lǐng)域,具體涉及例如在SOA環(huán)境中服務(wù)器端服務(wù)和 /或?qū)ο蟮臏y試,更具體地,涉及一種客戶服務(wù)器環(huán)境下測試邏輯與服務(wù)器 端對象的松耦合式測試方法和系統(tǒng)。
背景技術(shù):
目前,服務(wù)器端編程通常是基于容器的,且所述服務(wù)和相關(guān)業(yè)務(wù)邏輯 都位于不同的容器例如各種J2EE (Java 2平臺企業(yè)版)容器中。在SOA (面向服務(wù)架構(gòu))環(huán)境中,也同樣如此。服務(wù)和組件是在應(yīng)用服務(wù)器中提 供的,并由容器所維護(hù)。因此,如何為部署在服務(wù)器端容器中的這些服務(wù) 和底層邏輯實現(xiàn)代碼、以及相關(guān)輔助代碼構(gòu)造自動測試用例、并使得這種 測試如測試J2SE (Java 2平臺標(biāo)準(zhǔn)版)組件那樣方便靈活,是一個有待解 決的重要問題?,F(xiàn)有的測試工具都不夠方便靈活,諸如JUnit及其擴展、Apache Cactus、 Java Test System (JTS)等,因為它們是基于容器的測試框架。 就是說,由于測試邏輯將越來越多地依賴于由容器所提供的服務(wù)功能,測 試用例需要被打包和部署在服務(wù)器端容器中執(zhí)行。某些測試工具可以在客 戶端構(gòu)建測試裝具(test harness),并具有重定向代理以關(guān)聯(lián)服務(wù)器端的 測試用例(例如,Apache Cactus),或者具有servlet和XML配置文件以 暴露服務(wù)器端的測試用例(JUnitEE)。盡管如此,每當(dāng)測試用例有什么 變化時,就需要重新構(gòu)建測試用例,并將其重新部署到服務(wù)器上。圖l示 出了現(xiàn)有技術(shù)中的這樣一種典型的測試框架。為構(gòu)建用于基于容器的服務(wù)和組件(例如以Java編寫的)的真正靈
活的測試用例,特別是用于SOA環(huán)境中的服務(wù)測試的測試用例,可以考慮 釆用容器外的測試框架。另一種得到廣泛使用的技術(shù)是才莫擬對象(mockobject),它可在一定 程度上解決容器外測試的問題。但這種技術(shù)仍存在如下一些問題1.為容 器中的眾多復(fù)雜的組件和服務(wù)開發(fā)模擬對象是一種很繁重的任務(wù),在柏嚇 合的SOA環(huán)境中尤是如此;2.仍需要在容器內(nèi)使用真實對象進(jìn)行測試; 3.不可能實現(xiàn)模擬服務(wù)器。因此,模擬對象技術(shù)不能解決服務(wù)器端服務(wù)和 對象的測試問題。顯然,本領(lǐng)域中需要一種方便靈活的用于服務(wù)器端的服務(wù)和對象的測 試的方法和系統(tǒng)。發(fā)明內(nèi)容根據(jù)本發(fā)明的一個方面,提供了 一種客戶服務(wù)器環(huán)境下測試邏輯與服 務(wù)器端對象的t械合式測試方法,該方法包括以下步驟在客戶端創(chuàng)建服 務(wù)器端第一對象的代理;在客戶端部署的測試用例使用所述代理調(diào)用服務(wù) 器端的所述第一對象的方法,以進(jìn)行測試;以及當(dāng)所述調(diào)用服務(wù)器端的所 述第一對象的方法的步驟產(chǎn)生第二對象時,則由所述第一對象的代理在客 戶端自動創(chuàng)建所述第二對象的代理;其中,上述使用和自動創(chuàng)建步驟是遞 歸執(zhí)4亍的。根據(jù)本發(fā)明的另 一個方面,提供了 一種客戶服務(wù)器環(huán)境下測試邏輯與 服務(wù)器端對象的柏銅合式測試系統(tǒng),該系統(tǒng)包括在客戶端創(chuàng)建的服務(wù)器 端第一對象的代理,該代理被配置為可由在客戶端部署的測試用例4吏用 來調(diào)用服務(wù)器端的所述第一對象的方法,以進(jìn)行測試;且當(dāng)所述調(diào)用服務(wù) 器端的所述第一對象的方法的過程產(chǎn)生第二對象時,在客戶端自動創(chuàng)建所 述第二對象的代理;以及由上述使用和自動創(chuàng)建過程遞歸創(chuàng)建且具有上述功能的第二對象及其他對象的代理。
所附權(quán)利要求中闡述了被認(rèn)為是本發(fā)明的特點的新穎特征。但是,通 過在結(jié)合附圖閱讀時參照下面對說明性實施例的詳細(xì)說明將更好地理解發(fā)明本身以及其優(yōu)選^f吏用模式、另外的目標(biāo)、特征以及優(yōu)點,在附圖中圖1示出了現(xiàn)有技術(shù)中的一種典型的測試框架;圖2示出了根據(jù)本發(fā)明的實施例的一種客戶服務(wù)器環(huán)境下測試邏輯與 服務(wù)器端對象的木彿合式測試系統(tǒng);圖3示出了才艮據(jù)本發(fā)明的實施例的上述系統(tǒng)在測試用例中使用動態(tài)遞 歸代理以便將容器內(nèi)的測試邏輯從服務(wù)器端轉(zhuǎn)移到客戶端的過程和機制的 示例性示意圖;圖4示出了根據(jù)本發(fā)明的實施例的一種客戶服務(wù)器環(huán)境下測試邏輯與 服務(wù)器端對象的松耦合式測試方法;以及圖5示出了才艮據(jù)本發(fā)明的實施例的系統(tǒng)針對一示例測試邏輯在客戶端 和服務(wù)器端所執(zhí)行的具體步驟。
具體實施方式
下面參照附圖;^發(fā)明的實施例。然而,應(yīng)當(dāng)理解的是,本發(fā)明并不限 于所介紹的特定實施例。相反,可以考慮用下面的特征和元素的任意組合 來實施和實踐本發(fā)明,而無論它們是否涉及不同的實施例。因此,下面的 方面、特征、實施例和優(yōu)點僅作說明之用而不應(yīng)被看作是所附權(quán)利要求的 要素或限定,除非權(quán)利要求中明確提出。在此說明書內(nèi)對特征、優(yōu)點或類 似語言的提及并不是暗示可使用本發(fā)明實現(xiàn)的所有或某些特征和優(yōu)點在本 發(fā)明的任何單個實施例內(nèi)。相反,涉及特征和優(yōu)點的語言應(yīng)被理解為僅意 謂著與實施例相聯(lián)系地描述的特定特征、優(yōu)點和特性被包含在本發(fā)明的至 少一個實施例內(nèi)。本發(fā)明提供了一種用于服務(wù)器端服務(wù)和/或?qū)ο罄鏙ava對象的測試 的新的方法,該方法通過動態(tài)遞歸代理將原來的容器內(nèi)測試邏輯從服務(wù)器 端下移到客戶端。使用本發(fā)明,可以將測試邏輯的執(zhí)行步驟與測試代碼松 耦合化。換言之,本發(fā)明使能使用客戶端的代理來操縱容器中的遠(yuǎn)程服務(wù)
器端對象。所述動態(tài)遞歸代理具有以下特征 ■可覆蓋可在服務(wù)器端暴露的所有服務(wù)和Java類; ■當(dāng)需要時動態(tài)地和遞歸地創(chuàng)建代理,并且所述創(chuàng)建動態(tài)遞歸代理對于客戶端代碼是透明的; ■管理代理的生命周期與其相應(yīng)的對象的生命周期; ■可被用作模擬服務(wù)器。 這種靈活的方法實現(xiàn)了客戶端的測試邏輯,并且測試用例可通過動態(tài) 代理操縱真實的目標(biāo)對象。第一個遠(yuǎn)程對象需要通過遠(yuǎn)程動態(tài)代理被顯式 地創(chuàng)建,此后測試邏輯無需再顯式創(chuàng)建代理,而由本發(fā)明的系統(tǒng)自動生成 它們。因此,測試者可以4吏用通用的自動化測試框架例如用于Java測試的 JUnit以方便靈活的方式來開發(fā)和執(zhí)行他們的測試邏輯,并使用真實的容 器內(nèi)對象而不是模擬對象。當(dāng)發(fā)生任何變化時,測試者可以在客戶端作出 改變,并重新執(zhí)行測試用例,而無需將測試用例重新部署到服務(wù)器端。代理與其相應(yīng)的對象擁有相同的接口。即使調(diào)試器也無法將代理與其 對象區(qū)分開來。通過使用本發(fā)明,測試邏輯可以進(jìn)行API級別的調(diào)試,這 有助于在生產(chǎn)環(huán)境中的問題確定。因此,這些代理以在某種程度上實現(xiàn)了 模擬服務(wù)器。代理是以動態(tài)和遞歸的方式產(chǎn)生的。 一旦創(chuàng)建了新的代理,它將與所有現(xiàn)有的代理和非代理對象無縫地協(xié)同工作。換言之,該代理可以使用其 他代理和非代理對象作為a或被其他代理和非代理對象用作參數(shù),或在必要時返回新的代理作為返回值。這將極大縮短學(xué)習(xí)曲線用戶僅需要如 何創(chuàng)建第一個代理。代理與其相應(yīng)對象擁有相同的生命周期。代理與其相應(yīng)對象的創(chuàng)建幾 乎是同時發(fā)生的。當(dāng)代理在客戶端由例如Java垃圾收集器銷毀時,服務(wù)器 端相應(yīng)的對象將很快被銷毀。這防止了在長期運行中的內(nèi)存泄露問題。下面參照附圖以Java環(huán)境并更具體地以Java實現(xiàn)的SOA環(huán)境為例 來說明根據(jù)本發(fā)明的實施例的一種客戶服務(wù)器環(huán)境下測試邏輯與服務(wù)器端
對象的松耦合式測試方法和系統(tǒng)。本領(lǐng)域的技術(shù)人員可理解,本發(fā)明并不局限于Java環(huán)境或SOA環(huán)境,而是適用于任何客戶-服務(wù)器環(huán)境中的服務(wù) 器端對象的測試。圖2示出了根據(jù)本發(fā)明的實施例的一種客戶J艮務(wù)器環(huán)境下測試邏輯與 服務(wù)器端對象的^^合式測試系統(tǒng)。如圖所示,該系統(tǒng)包括在客戶端的代 理201,以及在服務(wù)器端的中介202。代理201位于客戶端的測試裝具中,并可與測試用例進(jìn)行交互,即由 測試用例調(diào)用以及將調(diào)用結(jié)果傳遞給測試用例。在本發(fā)明的一個實施例中, 所述代理201、測試用例、及其所在的測試裝具都位于J2SE環(huán)境中。而所 述中介202位于服務(wù)器端的容器中,并可與服務(wù)器端的容器中所部署的對 象交互,即調(diào)用所述對象,并獲得所述調(diào)用的結(jié)果。在本發(fā)明的一實施例 中,所述容器為J2EE容器,且所述中介為一個Javaservlet。且進(jìn)一步地, 該系統(tǒng)處于SOA環(huán)境中,且所述對象為服務(wù)和服務(wù)的支持對象例如Java 對象。在本發(fā)明的實施例中,所述代理201包括在客戶端創(chuàng)建的服務(wù)器端第 一對象的代理201以及在測試用例的執(zhí)行過程中由該第一對象的代理動態(tài) 和遞歸地創(chuàng)建的其他對象的代理201。獲得第 一對象的代理201的過程可以是典型的Java遠(yuǎn)程動態(tài)代理使用 場景,并且需要在客戶端獲得第一對象的接口或類。在Java中,提供了若 干實現(xiàn)動態(tài)代理的方法。例如,JDK提供了基于Java接口生成動態(tài)代理 的機制。此外,根據(jù)Java編譯類,也可能利用某些Java字節(jié)碼操縱框架 來創(chuàng)建代理。具體地,客戶端可向服務(wù)器端的中介202發(fā)送創(chuàng)建第一對象 的請求,服務(wù)器端的中介202根據(jù)所接收到的請求創(chuàng)建第一對象,例如 ServiceManager對象,將該對象及其索引標(biāo)識注冊在存儲器中的一注冊表 中,并向客戶端返回該對象的索引標(biāo)識和該對象的接口或類,而客戶端才艮 據(jù)接收到的該對象的索引標(biāo)識以及其接口或類,通過代理工廠創(chuàng)建該第一 對象的代理201。當(dāng)然,如果該第一對象的類或接口已在客戶端存在或已 由用戶指定,則不需要重新從服務(wù)器下載類或接口,而只需要首先在服務(wù) 器端創(chuàng)建該第一對象并返回該對象的索引標(biāo)識。另一方面,其他對象的代理201則可在測試過程中,當(dāng)由對第一對象或其他已生成對象的調(diào)用產(chǎn)生 其他新的對象時,由所述第一對象或其他已生成對象的代理201^^用Java以及接口或類來創(chuàng)建。如此動態(tài)遞歸創(chuàng)建的代理對于客戶端的測試用例來 說是透明的,即測試用例不需要顯式地創(chuàng)建除第 一對象之外的其他服務(wù)器 端對象的代理,它只需要創(chuàng)建或調(diào)用所述其他服務(wù)器端對象,而由本發(fā)明 的系統(tǒng)自動為其創(chuàng)建所需要的服務(wù)器端對象的代理。既可以僅在測試用例開始執(zhí)行時顯式創(chuàng)建一個第一對象的代理201, 并在測試用例的執(zhí)行過程中遞歸創(chuàng)建其他對象的代理201;也可以在測試 用例的執(zhí)行過程中多次顯式創(chuàng)建其他第一對象的代理201,并在測試用例 的執(zhí)行過程中由所述多個第一對象的代理201分別遞歸創(chuàng)建其他對象的代 理201。在本發(fā)明的一個實施例中,在客戶端的第一對象的代理201和由其創(chuàng) 建的其他對象對代理201以及在服務(wù)器端的相應(yīng)的第一對象及其他對象屬 于同一個M,并且所述注冊對象及其索引標(biāo)識包括將該對象及其索引標(biāo) 識注冊在其所屬的會話中。在本發(fā)明的一實施例中,^g"是通過cookie機 制創(chuàng)建和維護(hù)的。由此所生成的所述代理201具有與其相應(yīng)對^4目同的接口或方法。這 樣,對外部的使用者或調(diào)用者來說,所述代理201與其相應(yīng)的對象是完全 相同的,因此,測試用例可通過所述代理201調(diào)用所述第一對象的各方法。 并且,所生成的代理201可以與客戶端存在的所有其他已生成的代理以及 所有非代理對象相交互,也就^^兌,代理的方法能接受其他代理或非代理 對象作為M,而非代理對象的方法也能夠接收代理作為#。具體地,所述代理201 (包括所述第一對象的代理以及由所述笫一對 象的代理遞歸創(chuàng)建的其他代理)被配置為當(dāng)接收到測試用例對服務(wù)器端的 相應(yīng)對象的方法的調(diào)用時(在本文中,對對象的方法的調(diào)用應(yīng)被理解為也 包括對對象的域的操作),將所述測試用例對所勤目應(yīng)對象的方法的調(diào)用 通過網(wǎng)g遞給服務(wù)器端的中介202,以及從中介202接收所述調(diào)用的執(zhí) 行結(jié)果。在本發(fā)明的一個實施例中,所述代理201通過HTTP請求將所述 調(diào)用傳送給所述中介202。當(dāng)然,在本發(fā)明的其他實施例中,所述代理201 也可使用其他協(xié)議將所述調(diào)用傳送給所述中介。在本發(fā)明的一實施例中,所述代理201在將對相應(yīng)對象的方法的調(diào)用 通過網(wǎng)絡(luò)傳遞給服務(wù)器端的中介202之前,首先檢查該調(diào)用中的^M, 并將其中的代理替換為相應(yīng)的索引標(biāo)識,以便在服務(wù)器端的中介在接收到 所述調(diào)用之后,可根據(jù)調(diào)用^:中的索引標(biāo)識找到相應(yīng)的對象。此外,當(dāng)調(diào)用服務(wù)器端的對象的方法的過程產(chǎn)生新的對象時,所述代 理201可根據(jù)從中介202所接收到的所述新的對象的接口或類以及索引標(biāo) 識在客戶端自動創(chuàng)建所述新的對象的代理202,例如通過Java的動態(tài)代理 功能使用代理工廠來進(jìn)行創(chuàng)建。如此創(chuàng)建的新的對象的代理將具有與其相 應(yīng)對象相同的接口或方法,因而可由測試用例用來調(diào)用其相應(yīng)對象的方法, 從而可用來生成進(jìn)一步的新的對象的代理,并可與現(xiàn)有的代理以及非代理 對象相交互。此外,當(dāng)所迷代理201在調(diào)用服務(wù)器端的相應(yīng)對象的方法以進(jìn)行測試 的過程中發(fā)現(xiàn)缺少類時,它可通過網(wǎng)絡(luò)向所述中介202發(fā)送對該類的請求。 例如,當(dāng)所述代理201調(diào)用服務(wù)器端的相應(yīng)對象的方法的返回值為運行時 異常而在客戶端沒有該運行時異常的類時,所述代理201可向所述中介202 請求該運行時異常的類的代碼例如Java字節(jié)碼,并在從所述中介202接收 到到該類的代碼時^f吏用例如Java類加載器加載該類的代Z馬。此外,當(dāng)客戶端的代理201被釋放時,它可通過網(wǎng)絡(luò)向服務(wù)器端的所 述中介202發(fā)送釋放通知。例如,當(dāng)Java中的垃圾回收功能在一代理不再 存在引用時調(diào)用該代理的finalize方法將該代理銷毀時,或客戶端的測試 用例或測試裝具等主動通過調(diào)用代理的finalize方法來銷毀該代理(例如 在會話結(jié)束時,銷毀參與該會活的所有代理和對象,以及在測試結(jié)束時銷 毀所生成的所有代理和對象)時,該代理在被銷毀之前可例如通過HTTP 協(xié)議向服務(wù)器端的中介202發(fā)送包含被銷毀代理的對象索引標(biāo)識的釋放通
知,這樣,服務(wù)器端的中介202可在接收到所述銷毀通知后,根據(jù)銷毀通 知中的對象索引標(biāo)識銷毀相應(yīng)的對象,并取消對該對象及其索引標(biāo)識的注 冊,例如刪除存儲器中的注冊表中的相應(yīng)條目。這樣,可以動態(tài)和遞歸地創(chuàng)建服務(wù)器端的所有服務(wù)以及可暴露的對象 的代理,因而這些代理可用作模擬服務(wù)器。并且保證了代理的生命周期與 其相應(yīng)的對象的生命周期是一致的。在服務(wù)器端部署的所述中介202被配置為當(dāng)從網(wǎng)絡(luò)接收到來自客戶端 的代理201的對服務(wù)器端的相應(yīng)對象的方法的調(diào)用時,調(diào)用所述對象的方絡(luò)傳遞給客戶端的所述代理201。此外,所述中介202還^L配置為當(dāng)接收到來自客戶端的代理201的加 載類如加載異常類的請求時,從該請求中獲取該類的代碼的資源地址,從 所述資源地址獲取該類的代碼,并將該類的代碼通過網(wǎng)絡(luò)傳遞給戶端的代 理201。此外,如上所述,當(dāng)所述中介202通過網(wǎng)絡(luò)接收到來自客戶端的測試 用例的對所述第一對象的構(gòu)造方法的調(diào)用時,根據(jù)所接收到的調(diào)用來調(diào)用 所述第一對象的構(gòu)造方法,從而創(chuàng)建該第一對象;注冊該第一對象以及該 第一對象的索引標(biāo)識;并將該第一對象的索引標(biāo)識以及該第一對象的接口 或類通過網(wǎng)絡(luò)傳遞給客戶端,以使得客戶端根據(jù)接收到的該笫一對象的索 引標(biāo)識及接口或類創(chuàng)建該第一對象的代理。在這里,所述第一對象的構(gòu)造 方法應(yīng)3皮理解為也包括可用于創(chuàng)建該第一對象的、該第一對象類中的靜態(tài) 域以及其他靜態(tài)方法。在本發(fā)明的一實施例中,所述中介202被配置為在根據(jù)所接收到的調(diào) 用來調(diào)用相應(yīng)對象的方法之前,檢查所述調(diào)用的全部M,并將其中的索 引標(biāo)識替換為相應(yīng)的服務(wù)器端對象。此外,所述中介202被配置為當(dāng)所述調(diào)用所述對象的方法的過程產(chǎn)生 新的對象時,注冊該新的對象以及該新的對象的索引標(biāo)識;獲得該新對象 的接口或類;以及將該新對象的索引標(biāo)識以及該新對象的接口或類通過網(wǎng)
絡(luò)傳遞給客戶端的所述代理201。在本發(fā)明的一實施例中,所述中介202 將所述新的對象及其索引標(biāo)識注冊在該對象所屬的會話中。所述中介201可使用Java的固有功能,例如java.lang.Class和Java反射包中的API,來分析并獲得任何Java對象包括所述第一對象和新對象 的接口和操作。此外,所述中介202還被配置為當(dāng)接收到來自客戶端的代理201的釋 放通知時,根據(jù)所述通知中的索引標(biāo)識釋放相應(yīng)的對象,并取消該對象及 其索引標(biāo)識的注冊。在本發(fā)明的一實施例中,所述中介202將根據(jù)所述通 知中的索引標(biāo)識釋放相應(yīng)的對象,并在該對象所屬的會話中取消該對象及 其索引標(biāo)識的注冊。以上描述了根據(jù)本發(fā)明的實施例的一種客戶服務(wù)器環(huán)境下測試邏輯 與服務(wù)器端對象的爭鴻合式測試系統(tǒng),應(yīng)指出的是,所描述的系統(tǒng)僅為示 例,而不是對本發(fā)明的限制。本發(fā)明的系統(tǒng)可具有更多、更少或不同的模 塊,且各模塊之間的連接關(guān)系和包含關(guān)系可以不同。例如,所述代理201中的與所述中介202交互的功能也可由一單獨的模塊來執(zhí)行。圖3示意性地示出了根據(jù)本發(fā)明的實施例的上述系統(tǒng)在測試用例中使 用動態(tài)遞歸代理以便將容器內(nèi)的測試邏輯從服務(wù)器端轉(zhuǎn)移到客戶端的過程 和機制的示例。如圖所示,測試用例和代理都在J2SE環(huán)境中運行,而待測目標(biāo)對象 在服務(wù)器容器中運行。測試用例封裝了測試邏輯,測試邏輯使用對象代理 來調(diào)用對象方法,對象代理把對對象方法的調(diào)用傳遞到服務(wù)器端的中介, 而中介將創(chuàng)建和管理相應(yīng)的服務(wù)或Java對象實例。以這種方式,測試邏輯 4皮從服務(wù)器端下移到客戶端。具體地,如圖所示,在步驟l,測試用例使用第一動態(tài)代理201調(diào)用 相應(yīng)的遠(yuǎn)程對象的某種操作??蛻舳丝墒褂脤ο蠡虼碜鳛檩斎牒洼敵鰠?數(shù)。在步驟2,動態(tài)代理201通過HTTP請求向服務(wù)器端中介202發(fā)送請求。
在步驟3,服務(wù)器端的中介202在服務(wù)器端調(diào)用操作。 在步驟4,如果在服務(wù)器端創(chuàng)建了返回對象,則中介202將查找所有 的相關(guān)接口,并將對象及其索引標(biāo)識注冊在注冊表中。在步驟5,中介202將可用接口和對象索引標(biāo)識返回到客戶端的代理201。在步驟6,代理201創(chuàng)建相應(yīng)的其他代理,并將其返回給測試用例。該過程然后可返回步驟1,調(diào)用所述第一對象的其他操作或通過新生 成的代理201調(diào)用其相應(yīng)對象的某種操作,從而迭代執(zhí)行以上各步驟。下面參照圖4具體描述根據(jù)本發(fā)明的實施例的一種客戶服務(wù)器環(huán)境下 測試邏輯與服務(wù)器端對象的柏嚇合式測試方法。該方法可由上述本發(fā)明的 系統(tǒng)來執(zhí)行,因此,為敘述簡明起見,在以下對本發(fā)明的方法描述中省略 了與以上描述重復(fù)的部分內(nèi)容。如圖所示,在步驟401,在客戶端創(chuàng)建服務(wù)器端第一對象的代理。獲 得第一對象的代理的過程可以是典型的Java遠(yuǎn)程動態(tài)代理使用場景,并且 需要在客戶端獲得第一對象的接口或類。具體地,客戶端可向服務(wù)器端的 中介發(fā)送創(chuàng)建第一對象的請求,服務(wù)器端的中介根據(jù)所接收到的請求創(chuàng)建 第一對象,將該對象及其索引標(biāo)識注冊在一注冊表中,并向客戶端返回該 對象索引標(biāo)識和該對象的接口或類,而客戶端根據(jù)接收到的該對象的接口 或類以及索引標(biāo)識,通過代理工廠創(chuàng)建該第一對象的代理。當(dāng)然,如果該 第一對象的類或接口已在客戶端存在或已由用戶指定,則不需要重新W艮 務(wù)器下載類或接口 ,而只需要首先在服務(wù)器端創(chuàng)建該第一對象并返回該對 象的索引標(biāo)識。在測試用例的執(zhí)行過程中,即可以僅創(chuàng)建一個第一對象的代理,而所 有其他對象的代理都由該第 一對象的代理遞歸創(chuàng)建;也可以創(chuàng)建多個相同 或不同的第一對象的代理,每個所述第一對象的代理均遞歸創(chuàng)建其各自的 其他對象的代理。在客戶端創(chuàng)建第 一對象的代理的過程可由在客戶端部署的測試用例 在測試過程的一開始或在測試過程中發(fā)起,或由客戶端的測試裝具發(fā)起,
或由客戶端的其他組件發(fā)起。在步驟402,在客戶端部署的測試用例使用創(chuàng)建的代理調(diào)用服務(wù)器端 的相應(yīng)對象的方法,以進(jìn)行測試。就是說,在緊接著創(chuàng)建第一對象的代理 之后,可使用該第一對象的代理調(diào)用該第一對象的方法;而在遞歸創(chuàng)建了 其他對象的代理之后,可使用其他對象的代理調(diào)用相應(yīng)的其他對象的方法。 在進(jìn)行所述方法調(diào)用時,客戶端可使用客戶端存在的對象或代理作為輸入 和輸出M。在步驟403,所述代理將所述測試用例對所述第一對象的方法的調(diào)用 通過網(wǎng)絡(luò)傳遞給服務(wù)器端的中介。例如,所述代理可通過HTTP請求將所 述調(diào)用傳遞給服務(wù)器的中介。當(dāng)然,代理也可使用任何其他協(xié)議或技術(shù)將 所述調(diào)用傳遞給服務(wù)器的中介。在本發(fā)明的一實施例中,所述代理在將對所述第一對象的方法的調(diào)用 通過網(wǎng)絡(luò)傳遞給服務(wù)器端的中介之前,首先檢查該調(diào)用中的全部M,并 將其中的代理替換為相應(yīng)的索引標(biāo)識。在步驟404,所述中介在接收到來自客戶端的調(diào)用后,調(diào)用所述第一 對象的方法,以進(jìn)4亍測試。在本發(fā)明的一實施例中,所述中介在根據(jù)所接收到的調(diào)用來調(diào)用相應(yīng) 對象的方法之前,檢查所述調(diào)用的^參數(shù),并將其中的索引標(biāo)識替換為 相應(yīng)的服務(wù)器端對象。在步驟405,所述中介判斷所述調(diào)用是否產(chǎn)生了的第二對象。如果該判斷為所述調(diào)用產(chǎn)生了第二對象時,則在步驟406,由Ji艮務(wù)器 端的中介查找該第二對象的所有相關(guān)接口或類,并注冊該第二對象以及該 第二對象的索引標(biāo)識,例如將其注冊在該第二對象所屬的會話中。在步驟407,所迷中介將調(diào)用所述第一對象的方法的執(zhí)行結(jié)果例如正 常結(jié)果或關(guān)于異常的信息、以及所產(chǎn)生的第二對象的索引標(biāo)識及其接口或 類通過網(wǎng)絡(luò)例如使用HTTP協(xié)議傳遞給客戶端的所述第一對象的代理。在步驟408,所述第一對象的代理根據(jù)接收到的來自服務(wù)器端的中介 的所述第二對象的接口或類以及其索引標(biāo)識,自動創(chuàng)建所述第二對象的代 理。由此所生成的該第二對象的代理具有與所述第二對象相同的接口或 類。這樣,對外部的使用者或調(diào)用者來說,該代理與該第二對象是完全相 同的,此外,該第二對象的代理可以與客戶端存在的其他代理和對象相交 互。此外,該第二對象的代理還能夠?qū)⑺邮盏降膶υ摰诙ο蟮姆椒ㄕ{(diào) 用通過網(wǎng)絡(luò)發(fā)送到服務(wù)器端的中介,并能夠從服務(wù)器端的中介接收所述方 法調(diào)用的執(zhí)行結(jié)果,包括所述方法調(diào)用的返回值和異常等。如果所述方法 調(diào)用的返回一新的對象,則該代理能夠根據(jù)所返回的該新的對象的索引標(biāo) 識和接口或類生成該新的對象的代理。也就是說,該第二對象的代理能夠 動態(tài)地和遞歸地創(chuàng)建其他對象的代理。另一方面,如果步驟405的判斷為所述調(diào)用沒有產(chǎn)生新的對象,則執(zhí) 行步驟409,在該步驟中,中介將該調(diào)用的結(jié)果傳遞給代理。在步驟410,所述代理記錄所述執(zhí)行結(jié)果,以便由用戶進(jìn)行分析和調(diào) 適等。在測試用例的執(zhí)行過程中,在步驟411,可判斷一代理是否將被釋放。 例如,Java中的垃圾回收功能可在一對象不存在引用時調(diào)用該對象的 finalize方法將該對象銷毀。這樣,根據(jù)本發(fā)明的實施例實現(xiàn)的代理可判斷 其finalize方法是否被調(diào)用,以確定其是否將被釋放。當(dāng)然,在本發(fā)明的 其他實施例中,也可由客戶端的測試用例或測試裝具等主動通過調(diào)用代理 的finalize方法來釋放代理,例如,在一會話結(jié)束時釋放參與該會活的所 有代理。如果步驟411的判斷為是,則執(zhí)行步驟412,在該步驟中,當(dāng)客戶端 的一代理被釋放時,該代理在被釋放之前通過網(wǎng)絡(luò)向服務(wù)器端的中介發(fā)送 釋放通知。在步驟413,中介根據(jù)所接收到的釋放通知釋放相應(yīng)的對象,并取消 對該對象的注冊。當(dāng)中介已根據(jù)來自客戶端的釋放請求釋放了 一0中的所有對象后,
可進(jìn)一步地^r放該會活。在步驟414,由客戶端的測試用例或測試裝具等判斷是否繼續(xù)進(jìn)行測試。如果該判斷為是,則返回步驟402,繼續(xù)使用原來的代理或新創(chuàng)建的 代理調(diào)用服務(wù)器端的相應(yīng)對象,來進(jìn)行測試,從而迭代執(zhí)行以上過程,并 在測試過程中在必要時動態(tài)和遞歸地創(chuàng)建其他對象的代理。如果該判斷為否,則執(zhí)行步驟415,在該步驟中,分別在客戶端釋放 所有代理,以及通知中介在服務(wù)器端釋放所有相應(yīng)的對象,從而測試過程 結(jié)束。以上描述了根據(jù)本發(fā)明的實施例的 一種客戶服務(wù)器環(huán)境下測試邏輯 與服務(wù)器端對象的爭彿合式測試方法,應(yīng)指出的是,所描述的方法僅為示 例,而不是對本發(fā)明的限制。本發(fā)明的方法可具有更多、更不或不同的步 驟,且各步驟之間的順序可以不同或并行執(zhí)行。例如,所述判斷是否釋放 代理的步驟411以及所述判斷是否繼續(xù)進(jìn)行測試的步驟414可以在與圖中 所示不同的任何其他時刻執(zhí)行。下面給出一段示例測試邏輯。圖5示出了本發(fā)明的系統(tǒng)針對該示例測 試邏輯在客戶端和服務(wù)器端所執(zhí)行的具體步驟。ServiceManager serM = ServiceManager .INSTANCE;〃創(chuàng)建ServiceManager Service orderService = serM.locateService(',orderServicePartner"》 〃通過ServiceManager,查找到orderService。
orderService是 server端的一個service* DataObject order 1 = (DataObject) orderService.invoke C'createOrder", paras》〃調(diào)用orderService的createOrder方法,創(chuàng)建一個order,存入數(shù)據(jù)庫中。返回創(chuàng)建的名為orderl 的訂單對象。orderl .setString(key, value); 〃修改orderl中的 一個值. orderService.invoke("modifyOrder",orderl); 〃調(diào)用orderService的
modifyOrder方法,將修改后的orderl對象在數(shù)據(jù)庫中進(jìn)行更 新。下面給出在本發(fā)明的一示例性實施例中,以Java實現(xiàn)的本發(fā)明的系統(tǒng) 中的各部件的示例偽碼。應(yīng)當(dāng)指出的是,以下偽碼僅為示例,旨在使本領(lǐng) 域的技術(shù)人員可更好地理解本發(fā)明的基本思想,并可實施本發(fā)明,而不是 對本發(fā)明的限制。例如,所給出的偽碼示例中的客戶端通訊模塊也可被視 為包含在所述代理之中。示例偽碼1.代理的實現(xiàn)a)由接口列表創(chuàng)建代理Object newProxylnstance (Class[] interfaces, String keyld) { 1.由keyld創(chuàng)建InvocationHandler,所有代理的調(diào)用都會歸到Invocat ionHander的invoke方法處理.InvocationHander handler = new InvocationHandler0 {public Object invoke(Object targetobj, Method method,Object [] args) {1.1調(diào)用客戶端通訊;f莫塊String name = method, getName 0;Class[〗types = method. getParameterTypes0;Object rtobj = chat (keyld, name, types, args) , //參見chat方法偽碼1. 2處理結(jié)果1.2.1空指針的情況if (rtobj == null)return millj1. 2. 2返回值需^,j建代理或處理異常的情況 if (rtobj instanceof ChinRtObj) {
ChinRtObj chinRtObj = (ChinRtObj)rtobj; Throwable t = chinRtObj. getThrowable(); if (t!-null) throw t; 〃處理異常 Class [] interfs = chinRtObj. getlnterfaces () , String keyld = chinRtObj. getKeyld(); return ChinProxy. newProxylnstance (interf s, keyld) 5〃 重新調(diào)用生成新的代理。 1.2.3簡單類型與字符串} else if (ChinUtil. isPrinjitive(rttype) |j String, class, equals (rttype)) {// return type is primitive class or type or String return rtobjj 1. 2. 4數(shù)組} else if (rtobj. getClass 0. "Array 0) { 為數(shù)組里的每個值生成代理(如果需要的話)2.創(chuàng)建并返回代理Proxy. newProxylnstance(clasLoader, interfaces, handler) ,} b)第一個代理的創(chuàng)建 i.基于接口的第 一個代理的創(chuàng)建 1.方法的描述Object newProxylnstance(Class〖〗 interfaces, String implClassName, String name, Class [] types, Object [] args) interfaces 一接口歹寸表 implClassName —實現(xiàn)類名name -如果name為空指針,用于基于構(gòu)造方法的創(chuàng)建; 如果name不為空指針而types為空指針,用于基于靜態(tài)域的 創(chuàng)建,name指靜態(tài)域名; 如果name不為空指針而且types不為空指針,用于基于靜態(tài) 方法的創(chuàng)建;name指靜態(tài)方法名 types 一基于靜態(tài)方法創(chuàng)建時指方法^類型列表 args -基于靜態(tài)方法創(chuàng)建時指方法值列表 這個是一個通用的方法,實際的使用會有一些封裝,但最終的 調(diào)用都會歸結(jié)到這個方法. 2.方法的實現(xiàn)a) 調(diào)用客戶端通訊模塊,得到返回值Object obj = chat(implClassName, name, types, args);b) 處理結(jié)果返回的是代理if (obj instanceof ChinRtObj) {String keyld = ((ChinRtObj) obj) getKeyld0; returnChinProxy. newProxyInstance(interfaces, keyld);}c) 處理結(jié)果返回的不是代理 return obj;}基于類的第一個代理的創(chuàng)建1. 方法的描述Object newProxylnstance (Class implClass, Class [] typesObject [] args) 其中implClass為實現(xiàn)類 types -為實現(xiàn)類構(gòu)造方法^類型列表 args —為實現(xiàn)類構(gòu)造方法參數(shù)值2. 方法的實現(xiàn)當(dāng)前的實現(xiàn)使用了 ASM的字節(jié)碼生成工具,ASM相當(dāng)于Java的 匯編碼。
如何動態(tài)創(chuàng)建類的問題請參見ASM主頁 http: //asm. objectweb. org這里假設(shè)implClass為類A。大體的思路是,由實現(xiàn)類創(chuàng)建兩 個類, 一個是有其所有方法的接口C, 一個是其子類B。在其 子類B中創(chuàng)建一個域proxyInstance,該proxylnstance使用接 口C作為接口列表,使用基于接口的第一個代理的創(chuàng)建方式創(chuàng) 建;子類B重載父類A所有方法,并將所有方法調(diào)用引向 proxylnstance的調(diào)用;之后然后返回子類B的相應(yīng)實例作為 代理。由于子類B是父類A的子類,因此可以做一下反射 A a = (A) newProxylnstance(A. class, new Class[] 0, new Object [〗0);a)創(chuàng)建子類Bi.動態(tài)解析類A所有方法,生成Java接口C, C中包含A的所有方法 ii.基于構(gòu)造方法生成代理(name-null):String implClassNa邁e = implClass. getName0; Class [] interfaces = new Class [] {C. class}; proxylnstance = newProxylnstance(interfaces, implClassName, null, types, args); iii. 由implClass A動態(tài)生成其子類B, proxylnstance作 為子類B的一個域。子類B實現(xiàn)父類A的所有方法。示 例如下class B extends A { C —proxylnstance〃以下是某個方法的實現(xiàn)
返回類型methodA (參數(shù)列表){return -proxylnstance. methodA(^^i:歹ij表) ,b)返回子類的實例作為代理 i. 找到子類的相應(yīng)構(gòu)造方法Constructor constructor =subClass. getConstructor(types) ii. 返回子類實例return constructor, newlnstance(args);2.客戶端通訊模塊的實現(xiàn) a)客戶端通訊模塊的接口public Object chat(String target, String name, Class [] types, Object[] args),其中,target為真實對象的索引標(biāo)識或?qū)崿F(xiàn)類的全名。 name為所調(diào)用target上的方法或靜態(tài)域,如果為空指針,則指構(gòu)造 方法;如果name不為空指針且types為空指針,則是指靜態(tài)域;如果 name和types都不為空指針,則是指非構(gòu)造方法的一般方法。非構(gòu)造 方法的一般方法有兩類 一類是靜態(tài)的方法(類的方法), 一類是 非靜態(tài)的方法(對象的方法);當(dāng)target為實現(xiàn)類時,name和types 都不為空指針,name指靜態(tài)方法;當(dāng)target為真實對象的索引標(biāo)識 時,name和types都不為空指針,name指非靜態(tài)方法或靜態(tài)方法都可 以。types當(dāng)name指方法(包括一般方法和構(gòu)造方法)時,types為參數(shù) 類型列表args 當(dāng)name指方法(包括一般方法和構(gòu)造方法)時,args為;^lt
值列表b) 客戶端通訊;漠塊接口如何使用 當(dāng)前有兩個用途i.調(diào)用target上的參數(shù)類型為types的方法name,參數(shù)值為args, 獲得返回值,這里方法name有2種1. 類的方法,類的方法也有兩種a) 構(gòu)造方法,相當(dāng)于new A0b) 靜態(tài)方法,相當(dāng)與A.methodA(),其中methodA是類A的方 法。2. 對象的方法,相當(dāng)于A a - new A(); a.methodB0,其中 methodB是對象a的方法,使用A.methodB ()則調(diào)用不到;target也有兩種1. 實現(xiàn)類的全名如果name為實現(xiàn)類的全名,客戶端通訊模塊被用作第一個代理 的創(chuàng)建2. 真實對象的索引標(biāo)識 這時的調(diào)用的一^A代理的方法。有些系統(tǒng)的調(diào)用走的也是這 一個分支(比如垃圾回收)。ii.獲得target上名為name靜態(tài)域,返回值為靜態(tài)域 這個分支也是用于第一個代理的創(chuàng)建。c) 中介的客戶端的具體實現(xiàn)偽碼public Object chat (String target, String name, Class [] types, Object [] args) {1.創(chuàng)建到中介的連接URL url = newURL("http: 〃1ocalhost: 9080/vRecoveryTestWeb/.,.〃); //中介為一個servletHttpURIXoimection connect ion = (HttpURLCormecUon)ur 1. openComiec t i on 0 52. i殳置發(fā)送的cookie (利用cooke和session機制保持會話,結(jié) 合步驟6) sendCookies (connection) j //設(shè)置cookie3. 設(shè)置請求方法為POST,發(fā)送數(shù)據(jù)類型為Java序列化數(shù)據(jù). connection. setDoOutput(true)5connection. setRequestProperty ("Content—Type","application/x-java-serialized-object"); coimect ion. setReques tMethod ("POST")j4. 集結(jié)數(shù)據(jù),準(zhǔn)備往中介寫數(shù)據(jù)Object [] params = new Object〖]{ target, name, types, args };5. 往中介寫數(shù)據(jù)OutputStream outputStream =coimecUon. getOutputStream() ,writeObject (outputStream, params); 〃代理接受代理,實 現(xiàn)于此,詳見writeObject的偽碼。6. 接受這次的cookie以備下次請求發(fā)送 setCookies (connection);7. 接收數(shù)據(jù)InputStream inputStream = connection. getlnputStream(); Object obj 二 readObject (inputStream);//從月艮務(wù)端加栽 客戶端沒有的類實現(xiàn)于此,詳見readObject的偽碼 connect ion. disconnect 0 J // disconnect8. 返還結(jié)果 return objj}writeObject (OutputStream outputStream, Serializable params) {1.創(chuàng)建對象輸出流ObjectOutputStream oos - new ObjectOutputStream ( outputStream) { 〃重栽replaceObject方法,如果對象為代理,則替換為 Keyldprotected Object replaceObject (Object obj) throws IOException {如果obj為代理,從obj得到其KeyId并返回; 否則返回obj;2.寫對象因為使用的是重載的對象輸出流,對象params,包括其內(nèi)所有 其他對象的引用,都會調(diào)用replaceObject,檢查是否需要替換 為相應(yīng)KeyId。oos. wri te0b ject (params); oos. f lush() j oos. close 0 J Object readObject (I叩utStream inputStream) { 1.創(chuàng)建對象輸入流 ObjectlnputStream ois - newObjectlnputStream(inputStream) {〃重載resolveClass以檢查所有類是否完備 protected Class resolveClass (ObjectStreamClass desc) { try {return super. resolveClass (desc); } catch (ClassNotFoimdException e) {〃如果有類不存在則從遠(yuǎn)程類加栽器加載這個類String className = desc. getName (); return classLoader. loadClass(className);2.讀返回值這一步運行時,返回值依賴的每一個類都會經(jīng)resolveClass 檢查,如果發(fā)現(xiàn)不存在則遠(yuǎn)程加載。這里返回值包括正常返 回和異常返回。而異常返回經(jīng)常會有需要遠(yuǎn)程加載類定義的 情況發(fā)生Object obj = cois. readObject0; cois, close 0 J return objj}3.中介的實現(xiàn)a) 中介實現(xiàn)為一個servlet,中介有兩個任務(wù)i.客戶端使用GET請求從中介獲得類定義的字節(jié)碼 i i.客戶端4吏用P0ST請求通過中介調(diào)用真實對象的相應(yīng)方法b) 中介GET實現(xiàn)偽碼void doGet (HttpServletRequest req, HttpServletResponse resp) {1. 從所請求的URL中得到類的資源名 類的資源名和類名有一個簡單映射className. replace"', '/'). concat (". class"); String url = req, getRequestUR") toStringOjString resourcename = getResourceName(url);2. 從資源名得到字節(jié)碼并寫到輸出流 OutputStream out = resp. getOutputStream(); /oa說esowrce^^es(resourcename, out) 5}c)中介POST實現(xiàn)偽碼void doPost (HttpServletRequest req, HttpServletResponse resp) { try {1. 由相應(yīng)cookie得到相應(yīng)會話,結(jié)合l.c.chat第2步和第6步理 解HttpSession session = req. getSession(true)2. 從輸入流里讀#,由于M里可能有代理的Keyld,因此在 readParams里會做相應(yīng)替換,將代理的KeyId替換為真實對 象,詳見readParams方法的偽碼實現(xiàn)I叩utStream inputStream = req. getlnputStream() j Object〖]params = readParams(inputStream, session);3. 調(diào)用相應(yīng)方法并得到結(jié)果Object result = invoke(session, // session (String) params
, // target (String) params[1〗,// method name or field name (Class [])params [2], // types (Object []) params [3] ); // args4. 寫結(jié)果,詳見writeResult的偽碼 writeResult(resp. getOutputStreamO , result);5. 處理調(diào)用過程中的異常情況并將異常寫回客戶端 catch (InvocationTargetException e) { Throwable te -得到異常的根本原因 ChinRtObj rtobj = new ChinRtObj (null); rtobj. setThrowable(te)jwriteResult (resp. getOutputStreamO , rtobj);} readParams(InputStreaminputStream, final HttpSession session) { 1. 創(chuàng)建對象輸入流,重載resolveObject方法,把Keyld替換為 相應(yīng)真實對象。resolveObject的實現(xiàn)如下protected Object resolve0bjec"0bject obj) { if(obj instanceof Chin) { returnsession. getAttribute (((Chin) obj). getKeyldO); return objj2. 由對象輸入流讀對象并返回。 }void writeResult (OutputStream outputStream, Object result) {1. 創(chuàng)建對象輸出流ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)j2. 寫結(jié)果objectOutputStream. writeObject(result);objectOutputStream. f lushO;objectOutputStream. close 0; Object invoke(HttpSession session, String target, String name, Class [] types, Object [] args) {1.找目標(biāo)對象,目標(biāo)對象有三個可能值session本身,session里注冊的 值,以及空指針。Session本身和session里注冊的對象統(tǒng) 一處理,目標(biāo)對象為空指針^&j建新目標(biāo)對象處理 if (犯5^/0A equals (target)) { 〃判斷target對象是否
為session本身 targetObj = session; } else { //如果不是,在session找targettargetObj = session. getAttribute(target)5}2. 如果找不到,創(chuàng)建新的目標(biāo)對象,將目標(biāo)對象注冊到 session注冊表里,并返回目標(biāo)對象KeyIdif (targetobj == null) { Object obj = chinchilla (target, name, types, args); 〃 chichilla里的邏輯〃 1. if (name !- null && types -= null),由靜態(tài)域 創(chuàng)建// 2. else if (name != null && types != null), 由 靜態(tài)方法創(chuàng)建 〃 3. else由構(gòu)造方法創(chuàng)建ChinRtObj initkey - genRt0bject (); 〃產(chǎn)生一個唯一 的KeyId 〃注冊session. setAttribute(initkey. getKeyld(), obj); 〃返回return initkey;}3. 否則,調(diào)用目標(biāo)對象上的方法Method method =ChinUtil. ge度efAod(targetobj. getClass (), name, types) 5Object result - method, invoke(targetobj, args);4. 結(jié)果的處理primitive類型和數(shù)組 Class rtType = method. getReturnType0;// deal primitive typeif (result = null || ChinUti 1./'s戶ri邁/〃re(rtType)II rtType. equals (String, class)) { return result;〃處理數(shù)組if (result. getClass 0. isArrayO) { return arra7ffe卯"(session, result);5.結(jié)果的處理對象〃找返回對象類里的所有接口Class [] rtypes = find!nfer/"aces(result) ,〃生成有唯一KeyId的返回對象ChinRtObj rtobj = ge/^仍Je"0;〃注冊返回對象session. setAttribute (rtobj. getKeyldO, result); 〃設(shè)接口列表rtobj. setlnterfaces (rtypes) j返回結(jié)果return rtobj;4.垃圾回收的實現(xiàn)重載InvocationHandler的方法protected void finalize0 { 調(diào)用客戶端通訊模塊方法,將相應(yīng)的真實對象從session對象里移去, 真實對象的引用數(shù)會減一,如果真實對象的引用數(shù)為O,會ii^服務(wù)器 端的垃圾回收流程。
chat(SESSION, "removeAttribute", new Class [] { String, class }, new Object [] { keyld })需要注意的是,finalize由客戶端的垃圾回收器^,而不是用戶主動 調(diào)用。、keyld'可以由InvocationHandler得到,因為我們的創(chuàng)建我們自 己的InvocationHandler的時4矣已經(jīng)提供了 keyld 。 參見 Invoca t i onHand 1 er的創(chuàng)建一節(jié)。本發(fā)明可以硬件、軟件或其結(jié)合的方式實現(xiàn)。 一種典型的硬件和軟件 的組合可以是帶有計算機程序的通用計算機系統(tǒng),當(dāng)該計算機程序被加栽 和執(zhí)行時,控制該計算機系統(tǒng)而使其執(zhí)行本文中描述的方式。本發(fā)明優(yōu)選 地以分布方式實現(xiàn),在這種分布方式中,不同的部件分布在若干互連的計 算機系統(tǒng)中。本發(fā)明更優(yōu)選地在客戶服務(wù)器環(huán)境中實現(xiàn),在這種客戶服務(wù) 器環(huán)境中,客戶使用某種協(xié)議向服務(wù)器發(fā)送獲取信息或執(zhí)行操作的請求, 服務(wù)器進(jìn)行響應(yīng),以提供信息或執(zhí)行操作。適于執(zhí)行本文中描述的各方法 的任何計算機系統(tǒng)或其它裝置都是合適的。本發(fā)明也可體現(xiàn)在計算^MI序產(chǎn)品中,該程序產(chǎn)品包含使能實現(xiàn)本文 中描述的方法的所有特征,并且當(dāng)其,栽到計算機系統(tǒng)中時,能夠執(zhí)行 這些方法。盡管已參照優(yōu)選實施例具體示出和說明了本發(fā)明,但是本領(lǐng)域內(nèi)的那 些技術(shù)人員應(yīng)理解,可在形式和細(xì)節(jié)上對其進(jìn)行各種改變而不會背離本發(fā) 明的精神和范圍。
權(quán)利要求
1. 一種客戶服務(wù)器環(huán)境下測試邏輯與服務(wù)器端對象的松耦合式測試方法,該方法包括以下步驟在客戶端創(chuàng)建服務(wù)器端第一對象的代理;在客戶端部署的測試用例使用所述代理調(diào)用服務(wù)器端的所述第一對象的方法,以進(jìn)行測試;以及響應(yīng)于所述調(diào)用服務(wù)器端的所述第一對象的方法的步驟產(chǎn)生第二對象,由所述第一對象的代理在客戶端自動創(chuàng)建所述第二對象的代理;其中,上述使用和自動創(chuàng)建步驟是遞歸執(zhí)行的。
2. 根據(jù)權(quán)利要求1的方法,其中所述代理具有與其相應(yīng)對象 相同的接口或方法。
3. 根據(jù)權(quán)利要求1的方法,其中所述使用步驟包括以下子步所述測試用例通過所述代理調(diào)用服務(wù)器端的所述第一對象的方法;所述代理將所述測試用例對所述第一對象的方法的調(diào)用通過 網(wǎng)絡(luò)傳遞給服務(wù)器端的中介;所述中介根據(jù)所接收到的調(diào)用來調(diào)用所述第一對象的方法;以及所述中介將調(diào)用所述第一對象的方法的執(zhí)行結(jié)果通過網(wǎng)絡(luò)傳 遞給客戶端的所述代理。
4. 根據(jù)權(quán)利要求3的方法,還包括以下步驟 在所述代理將對所述第一對象的方法的調(diào)用通過網(wǎng)絡(luò)傳遞給服務(wù)器端的中介之前,將所述調(diào)用的參數(shù)中的代理替換為相應(yīng)的 索引標(biāo)識;以及在所述中介根據(jù)所接收到的調(diào)用來調(diào)用所述第一對象的方法之前,將所述調(diào)用中的索引標(biāo)識替換為相應(yīng)的服務(wù)器端對象。
5. 根據(jù)權(quán)利要求3的方法,其中所述自動創(chuàng)建步驟包括以下 子步驟當(dāng)所述中介調(diào)用所述第一對象的方法的子步驟產(chǎn)生第二對象 時,由所述中介注冊該第二對象以及該第二對象的索引標(biāo)識,且 其中,所述傳遞子步驟包括將所述第二對象的索引標(biāo)識以及該對 象的接口或類通過網(wǎng)絡(luò)傳遞給客戶端的所述第一對象的代理;以 及所述第一對象的代理根據(jù)接收到的所述第二對象的索引標(biāo)識 以及該第二對象的接口或類創(chuàng)建所迷第二對象的代理。
6. 根據(jù)權(quán)利要求3的方法,其中所述創(chuàng)建第一對象的代理的 步驟包括所述測試用例將對所述第一對象的構(gòu)造方法的調(diào)用通過網(wǎng)絡(luò) 傳遞給服務(wù)器端的所述中介;所述中介根據(jù)所接收到的調(diào)用來調(diào)用所述第一對象的構(gòu)造方 法,從而創(chuàng)建該第一對象;所述中介注冊該第 一對象以及該第 一對象的索引標(biāo)識;所述中介將該第 一對象的索引標(biāo)識以及該第一對象的接口或 類通過網(wǎng)絡(luò)傳遞給客戶端的測試用例;以及所述測試用例根據(jù)接收到的該第一對象的索引標(biāo)識及接口或 類創(chuàng)建該第一對象的代理。
7. 根據(jù)權(quán)利要求5或6的方法,其中所述第一對象和第一對 象的索引標(biāo)識以及所述第二對象和第二對象的索引標(biāo)識是在一會 話中注冊的。
8. 根據(jù)權(quán)利要求l的方法,還包括以下步驟 響應(yīng)于客戶端的一代理被釋放,該代理通過網(wǎng)絡(luò)向服務(wù)器端的中介發(fā)送釋放通知;以及所述中介根據(jù)所述通知釋放相應(yīng)的對象。
9. 根據(jù)權(quán)利要求3、 5、 6和8中任何一個的方法,其中所述 代理和所述中介之間的信息傳遞是通過HTTP協(xié)議進(jìn)行的。
10. 根據(jù)權(quán)利要求1的方法,其中該方法是在Java編程環(huán)境 中執(zhí)行的,所述對象在服務(wù)器端的J2EE容器中,所述中介為 servlet,且所述創(chuàng)建代理是通過Java的動態(tài)代理功能完成的。
11. 根據(jù)權(quán)利要求1的方法,其中該方法是在SOA環(huán)境中執(zhí) 行的,且所述對象為服務(wù)和/或服務(wù)的支持對象。
12. —種客戶服務(wù)器環(huán)境下測試邏輯與服務(wù)器端對象的松耦 合式測試系統(tǒng),該系統(tǒng)包括在客戶端創(chuàng)建的服務(wù)器端第一對象的代理,該代理被配置為 可由在客戶端部署的測試用例使用來調(diào)用服務(wù)器端的所 述第一對象的方法,以進(jìn)行測試;且響應(yīng)于所述調(diào)用服務(wù)器端的所述第一對象的方法的過程 產(chǎn)生第二對象,在客戶端自動創(chuàng)建所述第二對象的代理;以及由上述使用和自動創(chuàng)建過程遞歸創(chuàng)建且具有上述功能的第二 對象及其他對象的代理。
13. 根據(jù)權(quán)利要求12的系統(tǒng),其中所述代理具有與相應(yīng)對象 相同的接口或方法。
14. 根據(jù)權(quán)利要求12的系統(tǒng),該系統(tǒng)還包括在服務(wù)器端部署 的中介,且其中,所述被配置為可由在客戶端部署的測試用例使用來調(diào)用服務(wù) 器端的所述第一對象的方法、以進(jìn)行測試的代理被進(jìn)一步配置為 當(dāng)接收到所述測試用例對服務(wù)器端的所述第一對象的方法的調(diào)用 時,將所述測試用例對所述第一對象的方法的調(diào)用通過網(wǎng)絡(luò)傳遞 給服務(wù)器端的所述中介;所迷中介被配置為根據(jù)所接收到的調(diào)用來調(diào)用所述第一對 象的方法,并將調(diào)用所述第一對象的方法的執(zhí)行結(jié)果通過網(wǎng)絡(luò)傳 遞給客戶端的所述代理。
15. 根據(jù)權(quán)利要求14的系統(tǒng),其中,所述代理被進(jìn)一步配置 為在將對所述第一對象的方法的調(diào)用通過網(wǎng)絡(luò)傳遞給服務(wù)器端 的中介之前,將所述調(diào)用的參數(shù)中的代理替換為相應(yīng)的索引標(biāo)識; 以及所述中介被進(jìn)一步配置為在根據(jù)所接收到的調(diào)用來調(diào)用所 述第一對象的方法之前,將所述調(diào)用中的索引標(biāo)識替換為相應(yīng)的 服務(wù)器端對象。
16. 根據(jù)權(quán)利要求14的系統(tǒng),其中,所述中介被進(jìn)一步配置 為當(dāng)所述調(diào)用所述第一對象的方法產(chǎn)生第二對象時,注冊該第 二對象以及該第二對象的索引標(biāo)識;以及將所述第二對象的索引 標(biāo)識以及該對象的接口或類通過網(wǎng)絡(luò)傳遞給客戶端的所述第一對 象的代理;且其中,所述被配置為在客戶端自動創(chuàng)建所述第二對象的代理的第一 對象的代理被進(jìn)一步配置為根據(jù)接收到的所述第二對象的接口或 類創(chuàng)建所述第二對象的代理。
17. 根據(jù)權(quán)利要求14的系統(tǒng),其中,所述中介還被配置為 當(dāng)通過網(wǎng)絡(luò)接收到來自客戶端的對所述第一對象的構(gòu)造方法的調(diào)用時,根據(jù)所接收到的調(diào)用來調(diào)用所述第一對象的構(gòu)造方法,從而創(chuàng)建該第一對象;注冊該第 一對象以及該第 一對象的索引標(biāo)識; 將該第一對象的索引標(biāo)識以及該第一對象的接口或類通過網(wǎng)絡(luò)傳遞給客戶端,以使得客戶端根據(jù)接收到的該第一對象的索引標(biāo)識及接口或類創(chuàng)建該第一對象的代理。
18. 根據(jù)權(quán)利要求16或17的系統(tǒng),其中所述第一對象和第一 對象的索引標(biāo)識以及所述第二對象和第二對象的索引標(biāo)識是在一 會話中注冊的,
19. 根據(jù)權(quán)利要求12的系統(tǒng),其中,客戶端的所述代理還被配置為響應(yīng)于其被釋放,通過網(wǎng)絡(luò)向服務(wù)器端的所述中介發(fā)送釋放通知;以及所述中介還被配置為根據(jù)所述通知釋放相應(yīng)的對象。
20. 根據(jù)權(quán)利要求14、 16、 17或19的系統(tǒng),其中所述代理和 所述中介之間的信息傳遞是通過HTTP協(xié)議進(jìn)行的。
21. 根據(jù)權(quán)利要求12的系統(tǒng),其中該系統(tǒng)處于Java編程環(huán)境 中,所述對象在服務(wù)器端的J2EE容器中,所述中介為servlet, 且所述代理是通過Java的動態(tài)代理功能創(chuàng)建的。
22. 根據(jù)權(quán)利要求14的系統(tǒng),其中該系統(tǒng)處于SOA環(huán)境中, 且所述對象為服務(wù)和/或服務(wù)的支持對象。
全文摘要
公開了一種客戶服務(wù)器環(huán)境下測試邏輯與服務(wù)器端對象的松耦合式測試方法和系統(tǒng),該方法包括以下步驟在客戶端創(chuàng)建服務(wù)器端第一對象的代理;在客戶端部署的測試用例使用所述代理調(diào)用服務(wù)器端的所述第一對象的方法,以進(jìn)行測試;以及當(dāng)所述調(diào)用服務(wù)器端的所述第一對象的方法的步驟產(chǎn)生第二對象時,則由所述第一對象的代理在客戶端自動創(chuàng)建所述第二對象的代理;其中,上述使用和自動創(chuàng)建步驟是遞歸執(zhí)行的。
文檔編號G06F11/36GK101398779SQ20071016192
公開日2009年4月1日 申請日期2007年9月26日 優(yōu)先權(quán)日2007年9月26日
發(fā)明者南俊杰, 李正輝, 萌 王, 王紫瑤 申請人:國際商業(yè)機器公司