JUnit, 4, 5, Jupiter, Vintage

JUnit 5發布後,許多開發者都將這個出色的全新庫加入到他們的專案中,因為與其他版本不同,在這個新版本中,不需要從JUnit 4遷移到5,你只需將新庫包含到你的專案中,並使用JUnit 5的所有引擎,就可以用JUnit 5進行新的測試,而使用JUnit 4或3的舊測試將無問題地繼續運行。

但在一個大型專案中,一個十年前建立並並行運行兩個JUnit版本的專案,會發生什麼情況呢?

新的開發者開始在專案上工作,其中一些人具有JUnit經驗,另一些人則不然。使用JUnit 5創建新的測試,使用JUnit 4創建的新的測試,在某個時候,一位無知的新開發者在JUnit 5已經創建的測試中創建一個新情節時,他們只是包含了一個JUnit 4的注釋,測試就變成了混合型,有些是JUnit 4的@Test,有些是JUnit 5的@Test,而且每天移除JUnit 4庫都變得越來越困難。

那麼,如何解決這個問題呢?首先,你需要向你的團隊展示哪些是JUnit 5的,哪些是JUnit 4的,以便新的測試使用JUnit 5而不是JUnit 4創建。然後需要遵循童子軍規則,每次他們通過JUnit 4的測試時,都必須遷移到JUnit 5。

讓我們看看在JUnit 5中釋放的主要變化。一切從名稱開始,在JUnit 5中,你不會看到名為org.junit5的包,而是org.junit.jupiter。總結來說,所有你看見帶有“Jupiter”的東西,意味著它們來自JUnit 5。他們選擇這個名字是因為Jupiter以“JU”開頭,是太陽系中離太陽第五近的行星。

另一個變化是關於@Test,這個注解被移動到了一個新的包:org.junit.jupiter.api,現在不再使用像“expected”或“timeout”這樣的屬性,而是使用擴展。例如,對於超時,現在有一個專門的注解:@Timeout(value = 100, unit = TimeUnit.MILLISECONDS)。另一個變化是測試方法或類不需要是public的。

現在在測試配置中,你要使用@BeforeEach@AfterEach來代替@Before@After,並且還有@BeforeAll@AfterAll

為了忽略測試,現在你要使用@Disable來代替@Ignore

A great news that was released in JUnit 5 was the annotation @ParameterizedTest, with that is possible to run one test multiple times with different arguments. For example, if you want to test a method that creates some object and you want to validate if the fields are filled correctly, you just do the following:

Java

 

@ParameterizedTest
@MethodSource("getInvalidSources")
void shouldCheckInvalidFields(String name, String job, String expectedMessage) {
	Throwable exception = catchThrowable(() -> new Client(name, job));
  
  	assertThat(exception).isInstanceOf(IllegalArgumentException.class)
      .hasMessageContaining(expectedMessage);
}

static Stream<Arguments> getInvalidSources() {
	return Stream.of(Arguments.arguments("Jean Donato", "", "Job is empty"),
                     Arguments.arguments("", "Dev", "Name is empty"));
}

JUnit 5中有許多很棒的功能,我建議你查看JUnit 5的用戶指南,以分析對你的專案有用的內容。

現在所有的開發者都知道了JUnit 5中改變了什麼,你可以開始將JUnit 4從你的專案中移除的過程。所以,如果你在2024年還在使用JUnit 4,而且你的專案是一個大型專案,那麼你可能有一些依賴在使用JUnit 4。我建議你分析你的庫來檢查是否有一些正在使用JUnit 4。

在下面的圖片中我正在使用IntelliJ的依賴分析器。

正如你所看到的,jersey-test正在使用JUnit 4,也就是說,即使我從專案中移除了JUnit 4,JUnit 4仍然會可用,因為Jersey。最簡單的方式將是將jersey升級到2.35,因為JUnit 5已在jersey-test 2.35中引入,但我無法更新jersey-test框架,因為其他庫會在我的專案中報錯。所以,在這種情況下,我能做什麼呢?

I can exclude JUnit from Jersey with Dependency Exclusions from Maven (like the image below). That way JUnit 4 will not be used anymore, but rather our JUnit 5. 

當你運行一些使用Jersey的測試時,它們將不會被加載,因為Jersey中有使用JUnit 4注解的方法,setUptearDown,使用@Before@After。為了解決這個問題,你可以創建一個“配置類”它繼承自JerseyTest並實現setUptearDown,使用@BeforeEach@AfterEach調用super.setUp()super.TearDown()

Java

 

public class JerseyConfigToJUnit5 extends JerseyTest {

  @BeforeEach
  public void setUp() throws Exception {
  	super.setUp();
  }
  
  @AfterEach
  public void tearDown() throws Exception {
  	super.tearDown();
  }
}

因此,如果你已經檢查過你的庫,並且沒有人依賴於JUnit 4,你最終可以遷移所有你的測試到JUnit 5,對於這個過程,有一個很好的工具可以節省你很多工作,就是OpenRewrite,一個源代碼的自動重构生態系統,它們會將你所有的舊包、舊注釋以及所有東西改為新的。

就是这样,各位,現在你可以和你的隊友享受JUnit 5,並且放心,知道新的測試將會用JUnit 5創建,項目不會變成怪物。所以,記住,讓你的項目保持最新,因為如果你忘記了你的庫,每一天都會變得更難更新,總是使用規範,並且遵循規範的框架,並在代碼中擁有良好的設計,這樣你就可以輕鬆地進行更改和轉移。

Source:
https://dzone.com/articles/junit-4-5-jupiter-vintage-how-to-deal