Hamcrest Matchers的高级创建
介紹
上一次 ,我討論了Hamcrest Matcher是什么,如何使用以及如何制作。 在本文中,我將解釋創(chuàng)建Hamcrest Matchers的更多高級(jí)步驟。 首先,我將分享如何使您的匹配器更易于類型安全,然后介紹無(wú)狀態(tài)匹配器的一些技術(shù),最后是如何減少測(cè)試類上的大量靜態(tài)導(dǎo)入。 我還將給您一些有關(guān)命名靜態(tài)工廠方法的快速提示。
類型安全匹配器
您可能已經(jīng)在上次開發(fā)的matchs()方法中注意到了,我在注釋中指出,我曾使用“ yoda條件”來(lái)避免null檢查和類型檢查。 首先,自己對(duì)yoda條件進(jìn)行一些研究不會(huì)有什么壞處(我可能有一天會(huì)發(fā)表一篇有關(guān)它的文章,但不能保證),但是這里要注意的最大事情是某種類型檢查和需要空檢查。 這是因?yàn)閙atchs()方法接受一個(gè)對(duì)象,而不是Generics參數(shù)中指定的類型。
如Hamcrest的文檔中所述:
此方法與Object匹配,而不是與通用類型T匹配。這是因?yàn)镸atcher的調(diào)用者在運(yùn)行時(shí)不知道類型是什么(由于Java通用類型已擦除類型)。
因此,我們需要確定要傳入的對(duì)象的類型。此外,我們還應(yīng)確保沒有傳入任何空值(除非我們的特定Matcher可以這樣做,但這非常罕見),或者在至少要確保傳入的null不會(huì)導(dǎo)致NullPointerException。
但是有一種更簡(jiǎn)單的方法:TypeSafeMatcher。 如果擴(kuò)展此類而不是BaseMatcher類,它將為您執(zhí)行類型檢查和null檢查,然后將對(duì)象傳遞給僅采用泛型指定類型的匹配方法。
定義TypeSafeMatcher非常類似于我們上次定義Matcher的方式,但有一些區(qū)別:除了覆蓋matchs()之外,您還可以替代使用通用類型而不是Object的matchesSafely()。 而不是覆蓋describeMismatch(),而是覆蓋describeMismatchSafely()。 可能沒有一個(gè)新的describeTo()可能令人驚訝,但是看到它除了Description之外沒有其他內(nèi)容,因此不需要類型安全的版本。
否則,創(chuàng)建TypeSafeMatcher幾乎是相同的。
不過(guò),我不得不提我上周忘記的事情。 定義自己的Matchers的人不需要重寫describeMismatch()或describeMismatchSafely()方法。 BaseMatcher和TypeSafeMatcher都具有這些方法的默認(rèn)實(shí)現(xiàn),這些方法的簡(jiǎn)單實(shí)現(xiàn)是簡(jiǎn)單地輸出“ was item.toString() ”(如果TypeSafeMatcher獲得不正確類型的項(xiàng),則“ was of itemClassName ( item.toString()” )”。
這些默認(rèn)實(shí)現(xiàn)通常足夠好,但是如果使用的類型沒有toString()的有用實(shí)現(xiàn),則使用您自己的不匹配消息來(lái)描述該項(xiàng)目的問(wèn)題顯然更有用。 即使該類具有不錯(cuò)的toString()實(shí)現(xiàn),我也總是這樣做,因?yàn)樗梢愿斓亟鉀Q問(wèn)題。
有關(guān)其他可擴(kuò)展匹配器類的說(shuō)明
Hamcrest核心庫(kù)中還有其他幾個(gè)Matcher類,供用戶從中擴(kuò)展。 這些有幾種口味。
首先,有CustomMatcher和CustomTypeSafeMatcher。 這些設(shè)計(jì)用于通過(guò)匿名類一次性創(chuàng)建Matchers。 他們可能是有用的,但我更愿意總是在情況下,正確執(zhí)行我曾經(jīng)確實(shí)需要它一次。
接下來(lái),有DiagnosingMatcher和TypeSafeDiagnosingMatcher,它們使您可以在match()方法中創(chuàng)建不匹配描述。 這似乎是用一塊石頭殺死兩只鳥的好方法,但是我有幾塊牛肉:1)它違反了SRP 2)如果存在不匹配,它再次調(diào)用matchs()方法只是為了填充在不匹配說(shuō)明中。 因此,第一個(gè)調(diào)用將忽略獲取描述,第二個(gè)調(diào)用將忽略匹配。
您可以擴(kuò)展的最后一個(gè)特殊的Matcher是FeatureMatcher。 這可能非常有用,但理解起來(lái)很復(fù)雜(我不確定我是否理解正確–直到我嘗試自己動(dòng)手做一個(gè)或閱讀如何做一個(gè)為止)。 如果我弄清楚并獲得了很好的理解,我將在這里為您寫另一篇文章。
無(wú)狀態(tài)匹配器
不需要將任何內(nèi)容傳遞到其構(gòu)造函數(shù)(因此,它是靜態(tài)工廠方法)的任何Matcher都是無(wú)狀態(tài)Matcher。 它們與其他Matcher相比有一個(gè)很小的優(yōu)勢(shì),因?yàn)槟恍枰谌魏螘r(shí)候存在一個(gè)實(shí)例,就可以在需要使用該Matcher的任何時(shí)間重用它。
這是一個(gè)非常簡(jiǎn)單的補(bǔ)充。 您需要做的就是創(chuàng)建該類的靜態(tài)實(shí)例,并使您的靜態(tài)工廠返回該實(shí)例,而不是調(diào)用構(gòu)造函數(shù)。 庫(kù)附帶的IsEmptyString Matcher可以完成此操作(上一次我們的示例沒有,但這是為了簡(jiǎn)單起見)。
減少靜態(tài)進(jìn)口數(shù)量
用Hamcrest Matchers編寫了相當(dāng)多的測(cè)試之后,您可能會(huì)注意到文件頂部有很多靜態(tài)導(dǎo)入。 一段時(shí)間后,這可能會(huì)成為很大的麻煩事,所以讓我們看一下可以減輕此問(wèn)題的方法。
實(shí)際上,這幾乎與上一個(gè)解決方案一樣簡(jiǎn)單。 您可以通過(guò)創(chuàng)建本質(zhì)上為您執(zhí)行此操作的新類來(lái)減少靜態(tài)導(dǎo)入。 這個(gè)新類具有煩人的靜態(tài)導(dǎo)入,但隨后定義了自己的靜態(tài)工廠方法來(lái)委托給原始對(duì)象。 這是將一些核心Matchers組合到一個(gè)地方的示例:
import org.hamcrest.core.IsEqual; import org.hamcrest.core.IsNull; import org.hamcrest.core.IsSame; import org.hamcrest.Matcher;public class CoreMatchers {public static Matcher equalTo(T object) {return IsEqual.equalTo(object);}public static Matcher notNullValue() {return IsNull.notNullValue();}public static Matcher notNullValue(Class type) {return IsNull.notNullValue(type);}public static Matcher nullValue() {return IsNull.nullValue();}public static Matcher nullValue(Class type) {return IsNull.nullValue(type);}public static Matcher sameInstance(T target) {return IsSame.sameInstance(target);}public static Matcher theInstance(T target) {return IsSame.theInstance(target);} }然后,要使用任何或所有Matcher,只需靜態(tài)導(dǎo)入CoreMatchers。*還有一種生成這些組合Matcher類的方法,如官方Hamcrest教程所示 。 我不會(huì)繼續(xù)討論它,因?yàn)樗辉诒疚挠懻摲秶畠?nèi),而且我也不喜歡它。
結(jié)束提示:命名
如果您閱讀了官方的Hamcrest教程和/或查看了內(nèi)置的Matchers,您可能會(huì)注意到靜態(tài)工廠方法的命名趨勢(shì)。 通用語(yǔ)法匹配“斷言testObject是factoryMethod ”。 方法名稱的語(yǔ)法通常設(shè)計(jì)為可以在“ is”之前使用的當(dāng)前時(shí)態(tài)動(dòng)作。在命名自己的靜態(tài)工廠方法時(shí),通常應(yīng)遵循此約定,但實(shí)際上我建議將“ is”放入名稱中已經(jīng)。 這樣,Matcher的用戶無(wú)需將您的方法嵌套在is()方法內(nèi)。 但是,如果執(zhí)行此操作,則還需要?jiǎng)?chuàng)建反函數(shù)。 允許使用is()方法包裝Matcher的原因是,因此您也可以將其包裝在not()方法中,以測(cè)試已經(jīng)測(cè)試的內(nèi)容的逆函數(shù)。 這將導(dǎo)致類似“斷言testObject不是factoryMethod ”的句子。如果您認(rèn)為遵循約定對(duì)特定Matcher的限制太大,只需確保使用當(dāng)前的時(shí)態(tài)動(dòng)作測(cè)試即可。 例如,我做了一個(gè)匹配器,檢查是否拋出了一個(gè)異常,該異常的靜態(tài)工廠方法是throwsA()。 我只是不喜歡將它命名為throwingA()以便與“ is”一起使用。 但是,如果再次違反約定,則必須確定要?jiǎng)?chuàng)建一個(gè)靜態(tài)靜態(tài)工廠方法。 例如,如果要實(shí)現(xiàn)自己的逆工廠,最簡(jiǎn)單的方法通常是用not()包裝正工廠。 因此,我的nottThrowA()方法將返回not(throwsA())。 不過(guò)要小心:有時(shí)候,將正負(fù)誤轉(zhuǎn)實(shí)際上并不能給出您想要的正確逆。
奧托羅
好吧,這就是我為您準(zhǔn)備的。 如果您想讓我進(jìn)一步了解Hamcrest Matchers,請(qǐng)?jiān)谠u(píng)論中告訴我。 否則,您可以在其github頁(yè)面上的Hamcrest Matchers上進(jìn)行自己的研究。下周,我將討論如何讓您的Hamcrest Matchers以類似于AssertJ斷言的流暢方式檢查多個(gè)事情。
翻譯自: https://www.javacodegeeks.com/2015/01/advanced-creation-of-hamcrest-matchers.html
總結(jié)
以上是生活随笔為你收集整理的Hamcrest Matchers的高级创建的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: OPPO哭晕在厕所!新品两次被华为Mat
- 下一篇: 蚂蚁基金董事长王珺:智能AI让金融服务更