junit runner_了解JUnit的Runner架构
junit runner
幾周前,我開始創(chuàng)建一個(gè)小的JUnit Runner( Oleaster ),它允許您使用Jasmine方式在JUnit中編寫單元測試。 我了解到,創(chuàng)建自定義JUnit Runners實(shí)際上非常簡單。 在這篇文章中,我想向您展示JUnit Runners在內(nèi)部如何工作以及如何使用自定義Runners修改JUnit的測試執(zhí)行過程。
那么什么是JUnit Runner?
JUnit Runner是擴(kuò)展JUnit抽象Runner類的類。 運(yùn)行程序用于運(yùn)行測試類。 可以使用@RunWith注釋設(shè)置應(yīng)該用于運(yùn)行測試的Runner 。
@RunWith(MyTestRunner.class) public?class?MyTestClass?{@Testpublic?void?myTest()?{..} }JUnit測試是使用JUnitCore類開始的。 可以通過從命令行運(yùn)行它,也可以使用它的各種run()方法之一來完成此操作(如果您按run test按鈕,這就是您的IDE所做的事情)。
JUnitCore.runClasses(MyTestClass.class);然后,JUnitCore使用反射為通過的測試類找到合適的Runner。 此處的一個(gè)步驟是在測試類上查找@RunWith批注。 如果未找到其他運(yùn)行程序,則將使用默認(rèn)運(yùn)行程序( BlockJUnit4ClassRunner )。 將實(shí)例化Runner,并將測試類傳遞給Runner。 現(xiàn)在,實(shí)例化并運(yùn)行通過的測試類是Runner的工作。
跑步者如何工作?
讓我們看一下標(biāo)準(zhǔn)JUnit Runners的類層次結(jié)構(gòu):
Runner是一個(gè)非常簡單的類,實(shí)現(xiàn)了Describable接口,并具有兩個(gè)抽象方法:
public?abstract?class?Runner?implements?Describable?{public?abstract?Description?getDescription();public?abstract?void?run(RunNotifier?notifier); }方法getDescription()從Describable繼承,并且必須返回Description 。 描述包含了各種工具以后導(dǎo)出和使用的信息。 例如,您的IDE可能會(huì)使用此信息來顯示測試結(jié)果。 run()是一種非常通用的方法, 可以運(yùn)行某些內(nèi)容 (例如測試類或測試套件)。 我認(rèn)為通常Runner并不是您要擴(kuò)展的類(它太慷慨了)。
在ParentRunner中,事情變得更加具體。 ParentRunner是具有多個(gè)子代的Runner的抽象基類。 在這里重要的是要理解,測試是按層次結(jié)構(gòu)構(gòu)造和執(zhí)行的(就像樹一樣)。
例如:您可能運(yùn)行包含其他測試套件的測試套件。 這些測試套件可能包含多個(gè)測試類。 最后,每個(gè)測試類可以包含多個(gè)測試方法。
ParentRunner具有以下三種抽象方法:
public?abstract?class?ParentRunner<T>?extends?Runner?implements?Filterable,?Sortable?{????protected?abstract?List<T>?getChildren();protected?abstract?Description?describeChild(T?child);protected?abstract?void?runChild(T?child,?RunNotifier?notifier); }子類需要在getChildren()中返回泛型T的列表。 然后,ParentRunner要求子類為每個(gè)孩子(describeChild())創(chuàng)建一個(gè)Description,最后運(yùn)行每個(gè)孩子(runChild())。
現(xiàn)在,讓我們看一下兩個(gè)標(biāo)準(zhǔn)的ParentRunners:BlockJUnit4ClassRunner和Suite。
如果沒有提供其他Runner,則使用BlockJUnit4ClassRunner為默認(rèn)Runner。 因此,這是運(yùn)行單個(gè)測試類時(shí)通常使用的Runner。 如果您查看BlockJUnit4ClassRunner的來源,您將看到類似以下內(nèi)容:
public?class?BlockJUnit4ClassRunner?extends?ParentRunner<FrameworkMethod>?{@Overrideprotected?List<FrameworkMethod>?getChildren()?{//?scan?test?class?for?methonds?annotated?with?@Test}@Overrideprotected?Description?describeChild(FrameworkMethod?method)?{//?create?Description?based?on?method?name}@Overrideprotected?void?runChild(final?FrameworkMethod?method,?RunNotifier?notifier)?{if?(/*?method?not?annotated?with?@Ignore?*/)?{//?run?methods?annotated?with?@Before//?run?test?method//?run?methods?annotated?with?@After}} }當(dāng)然,這被過度簡化了,但是它顯示了BlockJUnit4ClassRunner的基本功能。 通用類型參數(shù)FrameworkMethod基本上是java.lang.reflect.Method的包裝,提供了一些方便的方法。 在getChildren()中,掃描測試類以查找使用@Test進(jìn)行反射的方法。 找到的方法包裝在FrameworkMethod對象中并返回。 describeChildren()從方法名稱創(chuàng)建一個(gè)Description,然后runChild()最終運(yùn)行測試方法。 BlockJUnit4ClassRunner在內(nèi)部使用了很多受保護(hù)的方法。 根據(jù)您要確切執(zhí)行的操作,最好檢查BlockJUnit4ClassRunner是否可以覆蓋方法。 您可以在GitHub上查看BlockJUnit4ClassRunner的源代碼。
Suite Runner用于創(chuàng)建測試套件。 套件是測試(或其他套件)的集合。 一個(gè)簡單的套件定義如下所示:
@RunWith(Suite.class) @Suite.SuiteClasses({MyJUnitTestClass1.class,MyJUnitTestClass2.class,MyOtherTestSuite.class }) public?class?MyTestSuite?{}通過選擇帶有@RunWith批注的Suite Runner來創(chuàng)建測試套件。 如果查看Suite的實(shí)現(xiàn),您會(huì)發(fā)現(xiàn)它實(shí)際上非常簡單。 Suite唯一要做的就是從使用@SuiteClasses批注定義的類中創(chuàng)建Runner實(shí)例。 因此,getChildren()返回Runner列表,runChild()將執(zhí)行委托給相應(yīng)的Runner。
例子
利用提供的信息,創(chuàng)建您自己的JUnit Runner并不難(至少我希望如此)。 如果您正在尋找一些示例自定義Runner實(shí)現(xiàn),則可以查看以下列表:
- Fabio Strozzi創(chuàng)建了一個(gè)非常簡單明了的GuiceJUnitRunner項(xiàng)目 。 它為您提供了在JUnit測試中注入Guice組件的選項(xiàng)。 來源GitHub
- Spring的SpringJUnit4ClassRunner可幫助您測試Spring框架應(yīng)用程序。 它允許您在測試類中使用依賴項(xiàng)注入或創(chuàng)建事務(wù)性測試方法。 來源GitHub
- Mockito為自動(dòng)模擬初始化提供了MockitoJUnitRunner 。 來源GitHub
- Oleaster的 Java 8茉莉花賽跑者。 源自GitHub (無恥的自我推廣)
結(jié)論
JUnit Runners具有高度可定制性,可讓您選擇更改以完成測試執(zhí)行過程。 很酷的事情是,可以更改整個(gè)測試過程,并且仍然使用IDE,構(gòu)建服務(wù)器等的所有JUnit集成點(diǎn)。
如果您只想進(jìn)行較小的更改,那么最好查看一下BlockJUnit4Class運(yùn)行程序的受保護(hù)方法。 您很有可能在正確的位置找到可重寫的方法。
翻譯自: https://www.javacodegeeks.com/2014/08/understanding-junits-runner-architecture.html
junit runner
總結(jié)
以上是生活随笔為你收集整理的junit runner_了解JUnit的Runner架构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wps表格做稿纸(用WPS文字表格工具实
- 下一篇: 烟非天赋101010(烟非天赋加点)