總結Junit4,Junit5,Jupiter之間的聯系
Junit5
目前Java領域內最為流行的單元測試框架 —— JUnit
Junit的最新版本JUnit5於2017年發佈。
Junit 5 = Junit Platform + Junit Jupiter + Junit Vintage
Junit Platform: Junit Platform是在JVM上啟動測試框架的基礎,不僅支持Junit自制的測試引擎,其他測試引擎也都可以接入。
Junit Jupiter: Junit Jupiter提供瞭JUnit5的新的編程模型,是JUnit5新特性的核心。內部 包含瞭一個測試引擎,用於在Junit Platform上運行。
Junit Vintage: 由於JUnit已經發展多年,為瞭照顧老的項目,JUnit Vintage提供瞭兼容JUnit4.x,Junit3.x的測試引擎。
Dependency
Junit4
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
當前dependency會引入junit:4.12和hamcrest-core:1.3的包
Junit vintage engine
<dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>5.6.2</version> <scope>test</scope> </dependency>
當前dependency會引入unit:4.13, apiguardian-api:1.1.0, hamcrest-core:1.3, junit-platform-commons:1.6.2,
junit-platform-engine:1.6.2, junit-vintage-engine:5.6.2, opentest4j:1.2.0的包
Jupiter
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.6.2</version> <scope>test</scope> </dependency>
當前dependency會引入apiguardian-api:1.1.0, junit-Jupiter-api:5.6.2, junit-platform-commons:1.6.2, opentest4j:1.2.0的包
Junit4和Junit5的註解區別
Junit5 | Junit4 | 說明 |
---|---|---|
@Test | @Test | 被註解的方法是一個測試方法。與 JUnit 4 相同。 |
@BeforeAll | @BeforeClass | 被註解的(靜態)方法將在當前類中的所有 @Test 方法前執行一次。 |
@BeforeEach | @Before | 被註解的方法將在當前類中的每個 @Test 方法前執行。 |
@AfterEach | @After | 被註解的方法將在當前類中的每個 @Test 方法後執行。 |
@AfterAll | @AfterClass | 被註解的(靜態)方法將在當前類中的所有 @Test 方法後執行一次。 |
@Disabled | @Ignore | 被註解的方法不會執行(將被跳過),但會報告為已執行 |
Junit4中的@Test是import org.junit.Test;
Jupiter中的@Test是import org.junit.jupiter.api.Test;
斷言
在Junit4和Junit5中均有標準斷言
斷言方法 | 說明 |
---|---|
assertEquals(expected, actual) | 如果 expected 不等於 actual ,則斷言失敗。 |
assertFalse(booleanExpression) | 如果 booleanExpression 不是 false ,則斷言失敗。 |
assertNull(actual) | 如果 actual 不是 null ,則斷言失敗。 |
assertNotNull(actual) | 如果 actual 是 null ,則斷言失敗。 |
assertTrue(booleanExpression) | 如果 booleanExpression 不是 true ,則斷言失敗。 |
Junit4中任何斷言失敗,測試就會在該位置失敗,意味著不會執行任何其他斷言。例如StudentTest中的should_test_every_test。
@Test public void should_test_every_test() { //given when int expected = 6; int actual = 10 - 4; Object nullValue = null; //then assertEquals(expected, actual); assertFalse(true); assertNull(nullValue); assertTrue(false); }
如果希望所有 斷言都會執行,即使一個或多個斷言失敗也是如此,該怎麼做呢?
可以使用Jupiter中提供的aseertAll方法
@Test @DisplayName("test assertAll") void should_test_every_test() { //given when int expected = 4; int actual = 2 + 2; Object nullValue = null; //then assertAll( "Assert All of these", () -> assertEquals(expected, actual), () -> assertFalse(nullValue == null), () -> assertNull(nullValue), () -> assertNotNull("Hello Word!"), () -> assertTrue(nullValue != null)); }
@DisplayName
可以在類和方法中添加@DisplayName註釋。這個名稱在生成報告時使用,這使得描述測試的目的和追蹤失敗更容易
運行單元測試後,點擊如下位置則可生成html報告
Student生成的單元測試報告為Test Results – StudentTest.html
StudentJupiterTest生成的單元測試報告為Test Results – StudentJupiterTest.html
校驗異常
Junit4提供瞭@Test(expected = Exception.class)的方式來校驗異常,但這種方式的缺點是,當兩個不同的業務拋出相同的業務異常,
而僅僅message不同時則無法精準的校驗。
@Test(expected = BusinessException.class) public void should_throw_business_exception_when_student_name_length_more_than_10() { //given when StudentCommand.builder() .name(RandomStringUtils.randomAlphanumeric(11)) .build(); } @Test(expected = BusinessException.class) public void should_throw_business_exception_when_student_description_length_more_than_20() { //given when StudentCommand.builder() .name(RandomStringUtils.randomAlphanumeric(9)) .description(RandomStringUtils.randomAlphanumeric(21)) .build(); }
當然也可以通過捕獲異常的方式,再判斷message,但這種方式不太優雅。
@Test public void should_validate_message_when_student_name_length_more_than_10() { //given when try { StudentCommand.builder() .name(RandomStringUtils.randomAlphanumeric(11)) .build(); } catch (BusinessException e) { assertEquals(e.getMessage(), "The length of student name exceed 10 chars."); } }
Jupiter提供瞭新的校驗方式,Assertions.assertThrows,在Junit的4.13的版本中,Asserts.assertThrows也提供瞭類似的功能
@Test @DisplayName("It tests the length of student name should less than 10 chars") void should_throw_business_exception_when_student_name_length_more_than_10() { //given when BusinessException businessException = Assertions.assertThrows(BusinessException.class, this::buildStudentName); //then assertEquals(businessException.getMessage(), "The length of student name exceed 10 chars."); } private void buildStudentName() { StudentCommand.builder() .name(RandomStringUtils.randomAlphanumeric(11)) .build(); } @Test @DisplayName("It tests the length of student description should less than 20 chars") void should_throw_business_exception_when_student_description_length_more_than_20() { //given when BusinessException businessException = Assertions.assertThrows(BusinessException.class, this::buildStudentDescription); //then assertEquals(businessException.getMessage(), "The length of student name exceed 20 chars."); } private void buildStudentDescription() { StudentCommand.builder() .description(RandomStringUtils.randomAlphanumeric(21)) .build(); }
到此這篇關於總結Junit4,Junit5,Jupiter之間的聯系的文章就介紹到這瞭,更多相關Junit4,Junit5,Jupiter之間的聯系內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- SpringBoot與單元測試JUnit的結合操作
- Java單元測試工具之JUnit的使用
- springBoot Junit測試用例出現@Autowired不生效的解決
- 基於SpringBoot Mock單元測試詳解
- Assert.assertEquals()方法參數詳解