JUnit規則

第一次偶然發現JUnit @Rule批注時,我對此概念有些惱火。 在測試用例中擁有一個公共領域似乎有些奇怪,因此我不愿意定期使用它。 但是一段時間后,我習慣了這一點,事實證明,規則可以通過多種方式簡化編寫測試的過程。 這篇文章簡要介紹了該概念,并簡要列舉了一些規則的優點。

什么是JUnit規則?

讓我們從一個現成的JUnit規則開始。 TemporaryFolder是一個測試幫助程序,可用于為臨時內容1創建位于文件系統目錄下的文件和文件夾。 TemporaryFolder的有趣之處在于,它保證在測試方法完成時刪除其文件和文件夾2 。 為了按預期方式工作,必須將臨時文件夾實例分配給@Rule注釋字段,該字段必須是公共的(不是靜態的),并且是TestRule的子類型:

public class MyTest {@Rulepublic TemporaryFolder temporaryFolder = new TemporaryFolder();@Testpublic void testRun() throws IOException {assertTrue( temporaryFolder.newFolder().exists() );}
}


它是如何工作的?

規則提供了一種攔截測試方法調用的可能性,就像AOP框架一樣。 與AspectJ中的周圍建議相比,您可以在實際測試執行之前和/或之后做一些有用的事情3 。 盡管這聽起來很復雜,但是卻很容易實現。

規則定義的API部分必須實現TestRule。 此接口稱為apply的唯一方法返回StatementStatement s表示(簡單地說)在JUnit運行時中的測試,而Statement#evaluate()執行它們。 現在,基本思想是提供Statement包裝擴展,該包裝可以通過覆蓋Statement#evaluate()來進行實際貢獻:

public class MyRule implements TestRule {@Overridepublic Statement apply( Statement base, Description description ) {return new MyStatement( base );}
}public class MyStatement extends Statement {private final Statement base;public MyStatement( Statement base ) {this.base = base;}@Overridepublic void evaluate() throws Throwable {System.out.println( 'before' );try {base.evaluate();} finally {System.out.println( 'after' );}}
}

MyStatement作為包裝器實現,在MyRule#apply(Statement,Destination)使用該包裝器包裝作為參數給出的原始語句。 很容易看出,包裝程序覆蓋了Statement#evaluate()在實際測試4之前和之后做一些事情。

下一個代碼片段顯示如何與上面的TemporaryFolder完全一樣地使用MyRule

public class MyTest {@Rulepublic MyRule myRule = new MyRule();@Testpublic void testRun() {System.out.println( 'during' );}
}

啟動測試用例將導致以下控制臺輸出,這證明我們的示例規則可以按預期工作。 測試執行被我們的規則攔截和修改,以在測試的“期間”前后打印“之前”和“之后”:

before
during
after

現在已經了解了基礎知識,下面讓我們看一下您可以使用規則執行的更有用的事情。

測試治具

從相應的維基百科部分引用的“測試裝置”是運行測試并期望獲得特定結果所必須具備的所有條件。 通常,通過處理單元測試框架的setUp()tearDown()事件來創建固定裝置。

使用JUnit,這通常看起來像這樣:

public class MyTest {private MyFixture myFixture;@Testpublic void testRun1() {myFixture.configure1();// do some testing here}@Testpublic void testRun2() {myFixture.configure2();// do some testing here}@Beforepublic void setUp() {myFixture = new MyFixture();}@Afterpublic void tearDown() {myFixture.dispose();}
}

考慮您在許多測試中以上面顯示的方式使用特定的夾具。 在那種情況下,最好擺脫setUp()tearDown()方法。 鑒于以上各節,我們現在知道可以通過更改MyFixture來實現TestRule來完成。 適當的Statement實現必須確保它調用MyFixture#dispose()并且看起來可能像這樣:

public class MyFixtureStatement extends Statement {private final Statement base;private final MyFixture fixture;public MyFixtureStatement( Statement base, MyFixture fixture ) {this.base = base;this.fixture = fixture;}@Overridepublic void evaluate() throws Throwable {try {base.evaluate();} finally {fixture.dispose();}}
}

有了這個,上面的測試可以重寫為:

public class MyTest {@Rulepublic MyFixture myFixture = new MyFixture();@Testpublic void testRun1() {myFixture.configure1();// do some testing here}@Testpublic void testRun2() {myFixture.configure2();// do some testing here}
}

在很多情況下,我開始欣賞使用規則編寫測試的更為緊湊的形式,但是可以肯定的是,這也是一個品味問題以及您認為更適合閱讀的內容5

帶有方法注釋的夾具配置

到目前為止,我已默默地忽略了TestRule#apply(Statement,Description)Description參數。 通常, Description描述了將要運行或已經運行的測試。 但它也允許訪問有關底層java方法的一些反射信息。 除其他外,有可能讀取這種方法附帶的注釋。 這使我們能夠將規則與方法注釋結合起來,以方便配置TestRule

考慮以下注釋類型:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Configuration {String value();
}

MyFixture#apply(Statement,Destination)中的以下代碼段結合使用,該代碼讀取注釋為特定測試方法的配置值…

Configuration annotation= description.getAnnotation( Configuration.class );
String value = annotation.value();
// do something useful with value

…上面演示MyFixture規則用法的MyFixture可以重寫為:

public class MyTest {@Rulepublic MyFixture myFixture = new MyFixture();@Test@Configuration( value = 'configuration1' )public void testRun1() {// do some testing here}@Test@Configuration( value = 'configuration2' )public void testRun2() {// do some testing here}
}

當然,由于注釋僅允許EnumClass es或String文字作為參數,因此后一種方法存在局限性。 但是在某些用例中,這已經足夠了。 restfuse庫提供了一個很好的示例,該示例將規則與方法注釋結合使用。 如果您對現實世界的示例感興趣,則應查看Destination規則6的庫實現。

最后,剩下的唯一要說的是,我很想聽聽您關于可以用來簡化日常測試工作的JUnit規則的其他有用示例的信息:

  1. 通常由System.getProperty( 'java.io.tmpdir' );返回的目錄System.getProperty( 'java.io.tmpdir' ); ?
  2. 在查看TemporaryFolder的實現時,我必須注意,它不會檢查文件刪除是否成功。 這可能是打開的文件句柄的情況下,一個薄弱點?
  3. 值得的是,您甚至可以用其他方法代替完整的測試方法?
  4. 包裝語句的委托放入try...finally塊中,以確保執行測試后的功能,即使測試失敗。 在這種情況下,一個AssertionError會被拋出,并且不是在finally塊語句都將跳過?
  5. 你可能注意到TemporaryFolder之初例子也不外乎夾具的使用情況?
  6. 請注意,restfuse的Destination類實現了MethodRule而不是TestRule 。 這篇文章基于最新的JUnit版本,其中MethodRule被標記為@DeprecatedTestRule代替MethodRule 。 但是,鑒于此職位的知識,仍然應該很容易理解實現?


參考:來自JCG合作伙伴 Frank Appel的JUnit規則 ,位于Code Affine博客上。

翻譯自: https://www.javacodegeeks.com/2012/11/junit-rules.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/370676.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370676.shtml
英文地址,請注明出處:http://en.pswp.cn/news/370676.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

微pe工具箱是微軟的嗎_微PE工具箱V2.0更新10內核

本帖最后由 韋小寶2 于 2017-3-22 21:26 編輯微PE工具箱V2.0發布更新了,鏈接:http://pan.baidu.com/s/1c9whpO 轉載自無憂論壇 07年,第一個XP內核通用PE工具箱發布。17年,第一個WIN10內核的微PE工具箱就此誕生。64位純內核&#x…

jq實現輪播圖

之前設計了一個校團委網站,里面有一個輪播圖效果,上網后查看了許多方法,覺得下面這個方法最為適用,記錄下來 js代碼: $(document).ready(function () {//無縫切換輪播var i 0;//索引var clone $(".banner .imgL…

關于圖片預加載的思考

引子&#xff1a; 很多時候&#xff0c;我們在寫html頁面的時候&#xff0c;當需要在頁面中加入圖片時&#xff0c;我們很自然地把圖片直接用<img>標簽放在了<body>里面&#xff0c;這本來是沒有多大問題的。 但是當圖片數量很多的時候&#xff0c;問題就來了。H…

oracle安裝中桌面模式與服務器模式的去別

桌面模式只能本機使用。 服務器模式可以在網絡中使用&#xff0c;也就是網絡中的其他服務器可以使用。 所以安裝時&#xff0c;如果是生產環境肯定是服務器模式。一般也都是服務器模式。 轉載于:https://www.cnblogs.com/zhjx0521/p/7803691.html

python不能創建字典的是_用Python創建帶有重復鍵的字典

用Python創建帶有重復鍵的字典 我有以下列表&#xff0c;其中包含重復的具有不同值的汽車注冊號。 我想將其轉換為字典&#xff0c;該字典接受汽車登記號的多個鍵。 到目前為止&#xff0c;當我嘗試將列表轉換為字典時&#xff0c;它消除了鍵之一。 如何制作具有重復鍵的字典&a…

python中int是什么的縮寫_python中int是什么類型

python中的基本數據類型1:雖然python中的變量不需要聲明&#xff0c;但使用時必須賦值整形變量浮點型變量字符型2:可以一個給多個變量賦值&#xff0c;也可以多個給多個變量賦值3:python3中有6個標準數據類型Number(數字)*True1*False0*數值的除法(/)總是返回一個浮點數&#x…

redis cli命令

redis安裝后&#xff0c;在src和/usr/local/bin下有幾個以redis開頭的可執行文件&#xff0c;稱為redis shell&#xff0c;這些可執行文件可做很多事情。 可執行文件作用redis-server 啟動redisredis-cliredis命令行工具redis-benchmark基準測試工具redis-check-aofAOF持久化文…

高級ZK:異步UI更新和后臺處理–第2部分

介紹 在第1部分中&#xff0c;我展示了如何在ZK應用程序中使用服務器推送和線程來執行后臺任務。 但是&#xff0c;這個簡單的示例具有一個重大缺陷&#xff0c;這使其對于實際應用程序而言是一種不好的方法&#xff1a;它為每個后臺任務啟動了一個新線程。 JDK5引入了Execut…

css清除浮動的原理

最近學習css發現了高度塌陷時候要清除浮動,為了理解清楚浮動原理,網上找了不少資料,發現都寫的不是很清楚,而且都是一模一樣的內容,我在里分享一下我對清楚浮動原理的理解, 如果你已經很了解什么是浮動和浮動的效果你可以直接跳轉到三.如何清除浮動(重點)閱讀 一.什么是浮動首…

SpringBoot03 項目熱部署

1 問題 在編寫springBoot項目時&#xff0c;經常需要修改代碼&#xff1b;但是每次修改代碼后都需重新啟動&#xff0c;修改的代碼才會生效 2 這么實現IDEA能夠像Eclipse那樣保存過后就可以自動進行刷新呢 將springBoot項目進行熱部署即可 3 如何實現SpringBoot項目的熱部署01 …

STM32實現流水燈

led.c #include"led.h"void Led_Init(void) {GPIO_InitTypeDef GPIO_VALUE; //???RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//???GPIO_VALUE.GPIO_ModeGPIO_Mode_Out_PP;//???? ????GPIO_VALUE.GPIO_PinGPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_…

jacob 報錯 Can't co-create object

問題&#xff1a;開始時一切正常&#xff0c;后來什么都沒該&#xff0c;出現Cant co-create object報錯&#xff0c;即是創建不了ActiveXComponent wdnew ActiveXComponent("Word.Application"); 偶爾發現任務管理器中word進程居然達到10個&#xff0c;而我沒有打開…

map分組后取前10個_map根據屬性排序、取出map前n個

/*** map根據value排序* flag 1 正序* flag 0 倒序** param map* param flag* return*/public static > LinkedHashMap sortByValue(Map map, int flag) {LinkedHashMap sortMap new LinkedHashMap<>();if (flag 1) {map.entrySet().stream().sorted(Comparator.c…

wxpython可視化_使用wxPython的繪圖模塊wxPyPlot進行數據可視化

[Python進階(四十)-數據可視化の使用matplotlib進行繪圖前言??matplotlib是基于Python語言的開源項目&#xff0c;旨在為Python提供一個數據繪圖包。我將在這篇文章中介紹matplotlib A #-*- coding: utf-8 -*- ############################################################…

在Java EE 6中將Bean驗證與JAX-RS集成

JavaBeans驗證&#xff08;Bean驗證&#xff09;是一種新的驗證模型&#xff0c;可作為Java EE 6平臺的一部分使用。 約束條件支持Bean驗證模型&#xff0c;該約束以注釋的形式出現在JavaBeans組件&#xff08;例如托管Bean&#xff09;的字段&#xff0c;方法或類上。 javax.…

如何讓浮動的元素換行??css

當你想要做成這種布局效果的時候 紫色框里面的內容那樣 它是一個列表 li元素是塊級元素 默認大小是父元素ul的寬 并且換行 如果li沒有背景的話那就不用管了 可是問題來了它不但有背景 而且是根據文字自適應的寬高 這就是inline-block類型的功能了 那么想讓li是inline-bl…

Python學習之類和實例

面向對象最重要的概念就是類&#xff08;Class&#xff09;和實例&#xff08;Instance&#xff09;&#xff0c;必須牢記類是抽象的模板&#xff0c;比如Student類&#xff0c;而實例是根據類創建出來的一個個具體的“對象”&#xff0c;每個對象都擁有相同的方法&#xff0c;…

解決sublime里面的vue高亮的問題

下載插件文件&#xff1a;https://github.com/vuejs/vue-syntax-highlight 直接在官網下載放在安裝時候的packages目錄下&#xff08;sublime text3\Sublime Text3\Data\Packages&#xff09; 在Packages文件夾下新建一個vue的文件&#xff0c;把第一步下載的文件復制進去 subl…

python矩形填充顏色_在Python中找到所有用0填充的矩形

假設我們有一個二進制2D矩陣&#xff0c;現在我們必須找到所有用0填充的矩形的起點和終點。我們必須牢記&#xff0c;矩形是分開的&#xff0c;彼此之間不接觸&#xff0c;但是它們可以接觸陣列邊界。僅包含單個元素的矩形也是可能的。所以&#xff0c;如果輸入像-101110111011…

python concat_python中merge、concat用法

轉載&#xff1a;https://blog.csdn.net/ly_ysys629/article/details/73849543 參考&#xff1a;https://blog.csdn.net/stevenkwong/article/details/52540605 數據規整化&#xff1a;合并、清理、過濾 pandas和python標準庫提供了一整套高級、靈活的、高效的核心函數和算法將…