日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用JUnit规则进行干净的集成测试

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用JUnit规则进行干净的集成测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JUnit Rules的優勢,尤其是在進行集成測試時,幾乎不能被高估。 在本文中,我們將闡明ExternalResource擴展的有用性。 在我們必須使用抽象外部資源的第三方庫的情況下,這些簡化了燈具控制。 作為示例,我們將看看如何基于Git提交日志消息來驗證對條目列表的正確檢索。

什么是集成測試?

“關注點分離”可能是軟件設計和實現中最重要的單個概念。
語用單元測試[HUTH03]

通常,我們使用單元測試來檢查一小段生產代碼是否按預期工作。 但是重要的是要了解,這類測試僅限于開發人員負責的代碼。 為了澄清這一點,請考慮合并第三方庫來管理對文件,數據庫,Web服務等的訪問。

測試將隱式調用第三方組件的代碼,因為我們的被測系統 (SUT)依賴于這些組件(DOC)[MESZ07]。 如果外部資源之一不可用,盡管開發人員的代碼可能沒有問題,但它們將失敗。 此外,訪問這些資源通常很慢,并且設置測試裝置通常很麻煩。 更不用說脆弱性了,它是由不同庫版本的潛在語義變化引起的。

所有這些缺點建議通過適配器抽象[FRPR10]將應用程序的代碼與第三方代碼分開。 不僅僅是抽象適配器組件可以在應用程序的問題域方面提供表達性的API,它還允許使用輕量級的替代測試double (通常表示為嘲笑)來替換基于第三方代碼的實現。

使用JUnit進行測試

使用JUnit進行測試是Java開發人員可以學習的最有價值的技能之一。 無論您的背景是什么,無論您是只是想建立一個安全網以減少桌面應用程序的性能下降,還是要基于健壯且可重用的組件來提高服務器端的可靠性,都需要進行單元測試。

弗蘭克(Frank)寫了一本書,為使用JUnit進行測試的基本知識提供了深刻的切入點,并為您準備了與測試有關的日常工作挑戰做好了準備。

學到更多…

這消除了先前列出的有關單元測試的依賴性問題。 雙重測試的設置費用低廉,可以將測試中的系統與第三方代碼隔離開,并保持測試的快速和可靠[MESZ07]。 但是,它剩下的工作是測試適配器組件的正確行為。 這是集成測試開始起作用的時候。

該術語指的是軟件測試中的階段,在該階段中,將各個軟件模塊組合在一起并作為一個組進行測試[INTTES]。 公平地說,我們使用適配器抽象將一個或多個第三方模塊組合在一起以提供某種功能。 因為從應用程序的角度來看,這樣的適配器是低級組件,所以這種策略隱式地導致了一種自下而上的方法,即首先測試最低級別的組件,然后再使用它來促進對更高級別的組件的測試。

您可能想知道為測試目的調整設計是否不是一件壞事。 但是,通過使用適配器,您可以確定應用程序和第三方代碼之間的明確界限。 如果新的庫版本引入的行為略有不同,則只需調整適配器代碼即可再次通過相應的集成測試。 您的實際應用程序代碼(包括單元測試)將不受影響! 此外,您可以通過提供適當的適配器輕松切換到其他供應商。 因此,遵循這種做法還可以帶來更健康的應用程序設計。 [APPE15]

外部資源處理

不幸的是,在編寫集成測試時,我們必須面對通過使用測試倍數來避免單元測試所遇到的問題。 特別是從編碼角度來看,安裝測試夾具通常需要大量的精力。 最重要的是,我們還必須妥善保管[MESZ07]。 例如,這意味著我們可能需要在測試執行后重置外部資源的狀態。 后者對于確保后續測試獨立運行很重要。 這樣一來,測試所做的資源修改就不會偽造其后繼者的驗證結果。

為了減少設置和拆卸代碼的重復開銷,將普通的段落交換到測試幫助程序類中似乎很自然。 考慮一下系統環境變量,主數據記錄等的創建,刪除或操作。 JUnit規則是特殊的測試助手,它像AOP框架一樣攔截測試方法調用。 與AspectJ中的環境建議相比,它們可以在實際測試執行之前和/或之后做有用的事情。 例如,可以在測試運行之前注冊REST服務資源,并在結束后自動將其刪除。

JUnit為規則提供了方便的基類ExternalResource ,這些規則用于在測試之前設置外部資源(文件,套接字,服務器,數據庫連接等),并保證隨后將其拆除[EXRAPI]。 以下清單ServerRule顯示了原理。

public class ServerRule extends ExternalResource {private final int port;public ServerRule( int port ) {this.port = port;}@Overrideprotected void before() throws Throwable {System.out.println( "start server on port: " + port );}@Overrideprotected void after() {System.out.println( "stop server on port: " + port );} }

ServerRule的構造函數使用我們的虛擬服務器類型的端口號。 為了證明這個概念,實際上我們不啟動一個真實的,但只打印出的調用含有消息這個號碼before和after的回調掛鉤。 下一個清單顯示ServerRule的用法。

public class MyServerITest {@Rulepublic final ServerRule serverRule = new ServerRule( 5050 );@Testpublic void foo() {System.out.println( "code that fails without server access" ); } }

請注意,該規則如何由帶有@Rule注釋的公共非靜態字段@Rule 。 運行測試用例將導致以下輸出。

start server on port: 5050 code that fails without server access stop server on port: 5050

如您所見,該規則確保測試代碼在預期的環境先決條件內執行,并自動進行內部管理。 為了加深這個主題,讓我們看一個更詳細的示例,該示例說明了規則管理的燈具與被測組件之間的相互作用。

設計用于Git集成測試的規則

標題圖像顯示了一個時間軸組件,該組件通過可配置的ItemProvider適配器檢索其Item列表。 捕獲圖片時使用的適配器類型從Git存儲庫讀取條目。 每個項目代表當前存儲庫分支的提交。 該插圖基于我為《 Testing with JUnit》一書開發的示例應用程序的屏幕截圖。 因為它超出了本書的范圍,所以我借此機會對我申請編寫JGit集成測試的GitRule助手進行了解釋。

驅動程序是提供實用程序類,其目的是簡化建立包含任意提交,分支等內容的git夾具存儲庫的任務。 為此,我創建了一個GitRepository類型。 這通過JGit處理本地存儲庫上的存儲庫交互。 以下摘錄應闡明概念。

public class GitRepository {private final File location;GitRepository( File location ) {this.location = location;}public RevCommit commitFi1e( String fileName, String content, String message )throws IOException{createFi1e( fileName, content );addFi1es();return commit( message );}[...] }

如您所見, GitRepository實例采用一個構造函數參數,該參數引用本地Git倉庫的工作目錄。 但是請注意構造函數的可見性限制。 這是因為抽象不負責處理存儲庫資源的生命周期。 對于后者,我們使用ExternalResource派生,如下面的清單所示。

public class GitRule extends ExternalResource {private final Set<File> repositories;public GitRule() {repositories = new HashSet<>();}@Overrideprotected void after() {repositories.forEach( repository -> delete( repository ) );}public GitRepository create( File location ) {createRepositoryOnDisk( location );GitRepository result = new GitRepository( location );repositories.add( location);return result;}private void createRepositoryOnDisk( File location ) {InitCommand init = Git.init();init.setDirectory( location );init.setBare( false );callInit( init );}private static void callInit( InitCommand init ) {try {init.call().close();} catch( GitAPIException exception ) {throw new GitOperationException( exception );}} }

GitRule可以作為工廠存儲特定測試所需的存儲庫資源。 此外,一旦完成測試執行,它就會跟蹤正確處置所需的位置。 所示版本僅在磁盤上創建本地存儲庫,但是當然可以對其進行增強以克隆遠程存儲庫。

ItemProvider接口依賴于擴展類型Item的通用類型參數。 因此, GitItemProvider類型返回GitItem實例作為查找結果,并且每個git項都是JGit RevCommit的封裝。 這樣說,很明顯,第三方代碼抽象可能會影響多個類。 以下代碼段顯示了一個簡單的集成測試方案。 GitRule提供了適用于創建實際提交的存儲庫。 后者用于驗證GitItem實例的正確實例化。

public class GitItemTest {@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();@Rule public final GitRule gitRule = new GitRule();@Testpublic void ofCommit() throws IOException {GitRepository repository = gitRule.create( temporaryFolder.newFolder() );RevCommit commit = repository.commitFi1e( "file", "content", "message" );GitItem actual = GitItem.ofCommit( commit );assertThat( actual ).hasId( getId( commit ) ).hasTimeStamp( getTimeStamp( commit ) ).hasContent( getContent( commit ) ).hasAuthor( getAuthor( commit ) );}[...] }

該測試使用TemporaryFolder規則來確保在可訪問目錄下創建存儲庫。 實際上,使用臨時文件夾規則應該使GitRule的資源刪除GitRule多余。 但是,由于它的默認清除機制不會檢查資源刪除是否成功(無論如何,硬檢查僅適用于最新的JUnit版本),所以我選擇不依賴它。 這很重要,因為使用JGit可以很容易地遇到打開文件句柄的問題。

此外,測試的驗證是通過定制的定制GitItemAssert斷言類和一些實用程序方法(靜態導入)完成的。 有了這個適當的位置之后,我們準備看一下更復雜的場景。

public class GitItemProviderITest {private static final String CLONE_NAME = "test";private static final int INITIAL_COMMIT_COUNT = 6;@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();@Rule public final GitRule gitRule = new GitRule();private GitRepository repository;private GitItemProvider provider;private File remoteLocation;private File destination;@Beforepublic void setUp() throws IOException {remoteLocation = temporaryFolder.newFolder();repository = createRepository( remoteLocation );destination = temporaryFolder.newFolder();provider = new GitItemProvider( remoteLocation.toURI().toString(),destination,CLONE_NAME );}@Testpublic void fetchItems() throws IOException {int fetchCount = INITIAL_COMMIT_COUNT / 3;List<GitItem> actual = provider.fetchItems( null, fetchCount );assertThat( actual ).isEqualTo( subList( 0, fetchCount ) ).hasSize( fetchCount );}private List<GitItem> subList( int fromIndex, int toIndex ) {return repository.logAll().stream().map( commit -> ofCommit( commit ) ).collect( toList() ).subList( fromIndex, toIndex );}[...] }

設置與之前的測試相似。 但是,我們的裝置存儲庫是通過委派給createRepository方法來創建的。 為了簡潔起見,我在此省略了詳細信息,因為該方法僅創建具有INITIAL_COMMIT_COUNT提交的存儲庫。 被測試的GitItemProvider組件采用三個構造函數參數。 第一個是夾具庫的位置,它將由提供者克隆。 為此,第二個參數定義一個目標目錄,而第三個參數將插入克隆存儲庫的文件夾名稱。

在練習階段,組件從其克隆的存儲庫中獲取可用提交的子集。 subList驗證該列表,該列表是由我們的燈具存儲庫中的方法subList計算得出的預期列表。 最后,這些規則負責客房整理。

如果要查看完整的示例代碼,請參閱GitHub存儲庫https://github.com/fappel/Testing-with-JUnit上可用的示例應用程序源。

摘要

這篇文章介紹了如何在編寫集成測試時將JUnit規則用于干凈的資源管理。 我們已經對什么是集成測試有了基本的了解,了解了ExternalResource測試實用程序擴展的工作原理,并詳細說明了使用示例。 當然,它的意義不僅僅在于初見。 熟悉此處顯示的原理后,您可能會考慮研究其他主題,例如使用ClassRule來處理持久性固定裝置, 規則鏈 , 環境變量等。

不能不告訴您我的書《 使用JUnit進行測試 》中的第6章“ 使用JUnit規則減少樣板”可作為免費閱讀樣本, 網址為https://www.packtpub.com/packtlib/book/Application%20Development/ 9781782166603/6 。 如果您還不厭倦我的麻煩,請大膽前進并抓住機會深入研究JUnit規則的世界……

因此,請記住,人們始終遵守規則–不要忘記分享知識&#55357;&#56841;

資源資源

  • [APPE15]:Appel, 使用JUnit測試 ,Packt Publishing,2015年
  • [EXRAPI]:ExternalResource,API DOC, http ://junit.org/apidocs/org/junit/rules/ExternalResource.html
  • [FRPR10]:Freeman,Pryce, 不斷發展的面向對象軟件,由Tests指導 ,Addison Wesley,2010年
  • [HUTH03]:Hunt,Thomas, 實用單元測試有限公司,2003年,2004年
  • [INTTES]:Wikipedia,IntegrationTesting, https ://en.wikipedia.org/wiki/Integration_testing
  • [MESZ07]:Meszaros, xUnit測試模式 ,Pearson Education,Inc.,2007年

翻譯自: https://www.javacodegeeks.com/2015/09/clean-integration-testing-with-junit-rules-3.html

總結

以上是生活随笔為你收集整理的使用JUnit规则进行干净的集成测试的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。