Spring是如何整合JUnit的?JUnit源碼關聯延伸閱讀

  • 2022 年 5 月 21 日
  • 筆記

上一篇我們回答了之前在梳理流程時遇到的一些問題,並思考了為什麼要這麼設計。

本篇是《如何高效閱讀源碼》專題的第十二篇,通過項目之間的聯繫來進行擴展閱讀,通過項目與項目之間的聯繫更好的理解項目。

本節內容:

  • TestRunner的執行流程

  • Spring如何整合JUnit

在我們使用Spring的項目中進行測試時,一般都需要添加下面一行註解:

@RunWith(SpringRunner.class


為什麼要使用這個註解呢?為了回答這個問題,我們先來了解一下TestRunner是如何執行的。

TestRunner的執行流程

在前面梳理的執行流程中,我們已經知道了JUnitCore是整個測試的入口,它構建了Runner實例,而Runner通過測試類構建了對應的測試模型,並通過Statement來執行,通過TestNotifier來通知TestListener來處理測試結果。

但是我們還沒有梳理出JUnitCore是如何構建出Runner的,現在我們從JUnitCore入手,將最後一塊拼圖補全,梳理出一個完整的測試執行流程。

入口方法很簡單,委託給了runMain方法來執行。

圖片

這裡只是將命令行參數parse為一個對象,然後通過參數配置來執行測試。 

注意到這裡的addListener了嗎?這裡構建了一個TextListener,通過addListener添加到了TestNotifier中。前面我們已經知道,測試結果是通過TestNotifier來通知TestListener的,而這裡就是向TestNotifier中添加TestListener實例的。這裡就補齊了前面流程中缺的一塊拼圖。

最後一行通過createRequest方法構建了一個Request來執行測試

這裡的run方法就是構建了基本的測試執行流程,調用了runner對象的run方法來執行具體的測試。前面我們已經梳理了TestRunner的方法的具體流程,這裡就將我們前面梳理的流程完整的串聯起來了

注意上面的request.getRunner,現在我們只需要梳理出Request是如何獲取到runner的,那麼整個執行流程就完整了。
讓我們回過頭來看createRequest方法。

這裡通過Request的靜態方法classes來構建Request。

這裡構建了一個AllDefaultPossibilitiesBuilder實例,通過builder實例來構建Runner。篇幅限制,我們就直接到AllDefaultPossibilitiesBuilder的runnerForClass方法,來看看builder是怎麼構建Runner的。

首先,構建了5個默認的RunnerBuilder,然後通過對應的RunnerBuilder來構建Runner,如果構建成功了,則直接返回對應的Runner去執行測試。

注意最後一個builder方法junit4Builder,從名字我們可以知道它是用來構建JUnit4Runner的,我們點進去確認一下。

的確是創建JUnit4對象的。

至此,我們整個的執行流程就梳理出來了:

 

  • JUnitCore根據參數,通過Request和Builder構建了對應的Runner實例

  • Runner通過測試類構建了對應的測試模型,並通過Statement來執行,通過TestNotifier來通知TestListener來處理測試結果

Spring如何整合JUnit

上面的流程和Spring整合JUnit有什麼關係呢?

前面我們知道Spring測試需要添加一個註解RunWith,我們注意上面的builder方法,其中有個builder方法是annotatedBuilder,我們來看這個方法。

 

此方法通過RunWith註解,找到了對應的類,然後進行了實例化,作為Runner進行返回。注意上面AllDefaultPossibilitiesBuilder的runnerForClass方法的循環,如果找到了Runner就直接返回了,而annotatedBuilder是比較靠前的,所以獲取到Runner後就不會再執行後面的builder了。Spring中就是使用SpringRunner來執行測試了。

而SpringRunner又是如何執行測試的呢?結合前面梳理的Runner流程,你可以自己嘗試去梳理看看。

總結

本文通過Spring如何結合JUnit的例子梳理出了JUnit4完整的執行流程,以及梳理出Spring結合JUnit的方式。通過此方式講述了如何通過關聯延伸閱讀將多個項目整合起來,更好的理解項目之間的關係。

下文將講解不同版本之間源碼的閱讀。