JUnit 和 Mockito 之間的區別
一、簡介
軟體測試是軟體開發生命週期中的關鍵階段。它幫助我們評估、識別和提高軟體的品質。
測試框架幫助我們使用預先定義的工具來促進這個過程。在本文中,我們將討論 JUnit、Mockito、它們如何幫助我們,以及這兩個框架之間的差異。
2.什麼是JUnit
JUnit 是最廣泛使用的單元測試框架之一,JUnit 5 是其最新一代。此版本專注於Java 8以上版本,並支援各種風格的測試。
JUnit 5 使用斷言、註解和測試執行器來執行測試案例。該框架主要針對單元測試。它主要關注方法和類,與項目的其他元素隔離。
與先前的版本不同,JUnit 5 由三個不同的子項目組成:
- JUnit 平台 – 對於在 JVM 上啟動測試框架至關重要
- JUnit Jupiter – 引入了新的程式設計模型(編寫測試的要求)和擴充模型(
Extension API
)來編寫新一代測試 - JUnit Vintage – 確保與使用 JUnit 3 和 Junit 4 編寫的測試相容
對於執行時,JUnit 5 需要 Java 8(或更高版本)。但是,仍然可以測試已經使用先前版本的 JDK 編譯的程式碼。
通用 JUnit 測試類別和方法如下所示:
public class JunitVsMockitoUnitTest {
@Test
public void whenUsingJunit_thenObjectCanBeInstantiated() {
InstantiableClassForJunit testableClass = new InstantiableClassForJunit();
assertEquals("tested unit", testableClass.testableComponent());
}
}
在上面的範例中,我們建立了一個簡單的InstantiableClassForJunit
類,其中包含一個傳回String
方法。此外,查看 Github 中的類,我們會發現對於assertEquals()
方法,我們匯入了Assertions
類別。這是一個明顯的例子,表明我們使用的是 JUnit 5 (Jupiter),而不是舊版本。
3.Mockito是什麼
Mockito 是由 Szczepan Faber 和朋友開發的基於 Java 的框架。它提出了一種不同的方法(與使用expect-run-verify的傳統模擬庫相比)。我們會詢問有關執行後互動的問題。
這種方法也意味著 Mockito 模擬通常不需要事先進行昂貴的設定。此外,它有一個精簡的 API,可以快速啟動模擬。只有一種模擬,並且只有一種創建模擬的方法。
Mockito 的其他一些重要功能包括:
- 模擬具體類別和介面的能力
- 小註解語法糖 –
@Mock
- 清除指向程式碼行的錯誤訊息
- 建立自訂參數匹配器的能力
添加了 Mockito 後,之前的程式碼如下所示:
@ExtendWith(MockitoExtension.class)
public class JunitVsMockitoUnitTest {
@Mock
NonInstantiableClassForMockito mock;
// the previous Junit method
@Test
public void whenUsingMockito_thenObjectNeedsToBeMocked() {
when(mock.nonTestableComponent()).thenReturn("mocked value");
assertEquals("mocked value", mock.nonTestableComponent());
}
}
查看同一個類,我們注意到我們在類名上添加了註釋( @ExtendWith)
。還有其他方法可以啟用 Mockito,但我們不會在這裡詳細介紹。
接下來,我們使用@Mock
註解模擬了所需類別的實例。最後,在測試方法中,我們使用了when().thenReturn()
構造。
最好記住在assert
方法之前使用此構造。這讓 Mockito 知道當呼叫模擬類別的特定方法時,它應該會傳回提到的值。在我們的例子中,這是“mocked value”
而不是通常返回的“some result”
。
4. JUnit 和 Mockito 之間的區別
4.1.測試用例結構
JUnit 使用註解建立其結構。例如,我們在方法上面使用@Test
來表明這是一個測試方法。或@ParametrizedTest
表示測試方法將使用不同的參數運行多次。我們使用@BeforeEach, @AfterEach, @BeforeAll,
和@AfterAll
來表示我們希望該方法在一個或所有測試方法之前或之後執行。
另一方面,Mockito 可以幫助我們使用這些註解的方法。 Mockito 提供了創建模擬物件、配置其行為(返回什麼)以及驗證發生的某些交互作用(該方法是否被呼叫、呼叫了多少次、使用什麼類型的參數等)的方法。
4.2.測試範圍
正如我們之前提到的,我們使用 JUnit 進行單元測試。這意味著我們創建邏輯來單獨測試各個元件(方法)。接下來,我們使用JUnit執行測試邏輯並確認測試結果。
另一方面,Mockito 是一個框架,可以幫助我們產生某些類別的物件(模擬)並在測試期間控制它們的行為。 Mockito 更多的是關於測試期間的交互,而不是實際進行測試本身。我們可以在測試時使用Mockito來模擬外部依賴。
例如,我們應該從端點接收答案。使用 Mockito,我們模擬該端點並在測試期間呼叫它時決定其行為。這樣我們就不必再實例化該物件了。此外,有時我們甚至無法在不重構該物件的情況下實例化它。
4.3.測試雙打
JUnit的設計重點是物件和測試替身的具體實現。後者意味著假貨和存根(而不是模擬)的實現。測試替身模仿真實的依賴關係,但對於我們想要實現的目標而言,其行為有限。
另一方面,Mockito 使用動態物件(使用反射創建的模擬)。當我們使用這些模擬時,我們會個性化並控制它們的行為以滿足我們的測試需求。
4.4.測試覆蓋率
JaCoCo 是一個與 JUnit 一起使用的測試覆蓋框架,而不是與 Mockito 一起使用。這是兩個框架之間差異的另一個明顯例子。
Mockito 是 JUnit 使用的框架。 JaCoCo(或其他程式碼覆蓋庫)只能與測試框架一起使用。
4.5.物件模擬
使用 Mockito,我們可以指定模擬物件的期望和行為,從而加快創建所需的測試場景。
JUnit 更關注使用斷言的單一元件測試。它沒有內建的模擬功能。
5. 結論
在本文中,我們了解了 Java 生態系統中兩個最受歡迎的測試框架。我們了解到 JUnit 是主要的測試促進者。它幫助我們創建結構和適當的環境。
Mockito 是補充 JUnit 的框架。它幫助我們透過模擬元素來測試各個元件,否則這些元素的實例化將非常複雜或根本無法建立。此外,Mockito 幫助我們控制這些元素的輸出。最後,我們還可以檢查所需的行為是否發生以及發生了多少次。
與往常一樣,程式碼可以在 GitHub 上取得。