帶你探索JUnit 5.4

油膩的Java發表於2019-03-27

Java最受歡迎的測試庫JUnit釋出了一個新版本5.4。自上一次5.3.2釋出以來,這個版本帶來了一些值得我們去嘗試的地方,本文中,我將介紹最重要的內容,並在適用的地方提供程式碼示例。

你可能知道,JUnit 5.x(Jupiter)是對JUnit 4.x(Vintage)的巨大改進。JUnit 5是一個更優秀的版本,包括Lambda支援,JUnit 5擴充套件,測試方法引數注入以及許多其他功能。JUnit 5.4是JUnit 5的演變,進一步改善了測試體驗。

什麼是Junit 5?

官方使用說明

JUnit 5 = JUnit平臺 + JUnit Jupiter + JUnit Vintage

以下是原文就不翻譯了。

The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the [TestEngine](https://junit.org/junit5/docs/current/api/org/junit/platform/engine/TestEngine.html)API for developing a testing framework that runs on the platform. Furthermore, the platform provides a Console Launcher to launch the platform from the command line and a JUnit 4 based Runner for running any TestEngine on the platform in a JUnit 4 based environment. First-class support for the JUnit Platform also exists in popular IDEs (see IntelliJ IDEAEclipseNetBeans, and Visual Studio Code) and build tools (see GradleMaven, and Ant).

JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. The Jupiter sub-project provides a TestEngine for running Jupiter based tests on the platform.

JUnit Vintage provides a TestEngine for running JUnit 3 and JUnit 4 based tests on the platform.

Junit 5 對應的JDK版本一定要是1.8以上

JUnit 5.4入門

0.png

要開始使用JUnit 5.4,通過Maven引入。使用JUnit 5.4已經簡化了。而在先前版本的JUnit 5中,需要分別匯入幾個Jar包(例如,jupiter-api,jupiter-params,jupiter-engine),新版本允許你通過包括僅僅單一的使用JUnit 5.4 junit-jupiter依賴性聚集工件。

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.4.1</version>
    <scope>test</scope>
</dependency>

複製程式碼

專案程式碼結構

專案程式碼結構.png

@TempDir支援臨時目錄

在測試時,有時你需要訪問臨時檔案。JUnit 5現在提供了一個建立和清理臨時檔案的擴充套件,而不是自己處理這樣一個檔案的建立。您可以使用它來放置@TempDirectory註釋Path或File測試輸入引數或欄位。一個例子:


@Test
void writeItemsToFile(@TempDir Path tempDir) throws IOException {
		Path file = tempDir.resolve("test.txt");
		new ListWriter(file).write("a", "b", "c");
		assertEquals(singletonList("a,b,c"), Files.readAllLines(file));
	}
複製程式碼

引數化測試null和空支援

引數化測試是為了測試的時候提供好的入參,比如下面的的Limit就會直接列印Limit的所有列舉列表

public enum Limit {
    IN(1,"包含"),
    NOT_IN(0,"不包含");
	public final int value;
	public final String alias;
	Limit(int value, String k) {
		this.value = value;
		this.alias = k;
	}
}
複製程式碼

@ParameterizedTest
@EnumSource(Limit.class)
void checkLimit(Limit limit) {
   assertTrue(limitCheck.isValid(limit));
}

複製程式碼

但是,在這樣的設定中,假如我們需要去測試極端場景下,程式碼的健壯性,模擬提供null元素有點困難,或者在其他情況下,提供空元素。@NullSource(並@EmptySource加@NullAndEmptySource)就可以幫助到我們。 @NullSource相當於Mock了一個Null值做為入參,以此我們可以去測試程式碼

@ParameterizedTest
@NullSource // now also null is tested
@EnumSource(Limit.class)
void checkLimit(Limit limit) {
   assertTrue(limitCheck.isValid(limit));
}
複製程式碼

設定單元測試名稱

通常,在使用測試類時,可以使用@DisplayName註釋覆蓋測試方法名稱或類。例如,見下文

@Test
@DisplayName("計算加法的一個單元測試")
public void add() { }
複製程式碼

雖然上面提供了更易讀的格式,但它非常靜態。您現在可以做的是根據例如巢狀類或方法名稱生成顯示名稱。可以在文件中找到一個好的DisplayNameGeneration示例

如何排序JUnit 5測試方法?

雖然通常將測試方法相互依賴並不是一個好主意,但對於某些情況,在測試執行中有一定的順序是很方便的。例如,一個測試可能在REST端點中建立資源,而其他測試則驗證此資源的某些屬性。

在以前版本的JUnit中,這很難做到,但是從5.4開始,你可以使用一個新TestMethodOrder命名的OrderAnnotation。你可以以此來結合使用,Order以強制按特定順序執行測試方法。


@TestMethodOrder(OrderAnnotation.class)
class SequenceTest {

    @Test
    @Order(1)
    void createResource() {
        // Create a resource first...
    }

    @Test
    @Order(2)
    void verify() {
        // ...then verify some attributes.
    }
}
複製程式碼

下一步?

新的JUnit 5版本中還有許多其他功能,可以在官網找到。除了框架之外,JUnit 5的一大優點是文件很好。有很多可用的文件,其中的概念用非常簡單的程式碼示例進行了解釋,這一點我覺得和Spring的官網說明一樣具有高質量,簡單清晰。

如果您尚未升級到JUnit 5,那麼最新版本提供了許多強大的功能,這些功能將使遷移變得有價值。

相關文章