前置條件
JUnit 5 中的前置條件(assumptions【假設】)類似於斷言,不同之處在於不滿足的斷言會使得測試方法失敗,而不滿足的前置條件只會使得測試方法的執行終止。前置條件可以看成是測試方法執行的前提,當該前提不滿足時,就沒有繼續執行的必要。
@Test
@DisplayName("assumptions")
public void testAssumptions(){
assumeTrue(true);
assumeFalse(true);
System.out.println("assumptions");
}
嵌套測試
JUnit 5 可以通過 Java 中的內部類和@Nested 注解實現嵌套測試,從而可以更好的把相關的測試方法組織在一起。在內部類中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的層次沒有限制。
嵌套測試情況下,外層的Test不能驅動內層的Before(After)Each/All之類的方法提前/之后運行
@DisplayName("嵌套測試")
class NestedTest {
Stack<Object> stack;
@Test
@DisplayName("is instantiated with new Stack()")
void isInstantiatedWithNew() {
new Stack<>();
}
@Nested
@DisplayName("when new")
class WhenNew {
@BeforeEach
void createNewStack() {
stack = new Stack<>();
}
@Test
@DisplayName("is empty")
void isEmpty() {
assertTrue(stack.isEmpty());
}
@Test
@DisplayName("throws EmptyStackException when popped")
void throwsExceptionWhenPopped() {
assertThrows(EmptyStackException.class, stack::pop);
}
@Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
assertThrows(EmptyStackException.class, stack::peek);
}
@Nested
@DisplayName("after pushing an element")
class AfterPushing {
String anElement = "an element";
@BeforeEach
void pushAnElement() {
stack.push(anElement);
}
@Test
@DisplayName("it is no longer empty")
void isNotEmpty() {
assertFalse(stack.isEmpty());
}
@Test
@DisplayName("returns the element when popped and is empty")
void returnElementWhenPopped() {
assertEquals(anElement, stack.pop());
assertTrue(stack.isEmpty());
}
@Test
@DisplayName("returns the element when peeked but remains not empty")
void returnElementWhenPeeked() {
assertEquals(anElement, stack.peek());
assertFalse(stack.isEmpty());
}
}
}
}
參數化測試
參數化測試是JUnit5很重要的一個新特性,它使得用不同的參數多次運行測試成為了可能,也為我們的單元測試帶來許多便利。
利用@ValueSource等注解,指定入參,我們將可以使用不同的參數進行多次單元測試,而不需要每新增一個參數就新增一個單元測試,省去了很多冗余代碼。
@ValueSource: 為參數化測試指定入參來源,支持八大基礎類以及String類型,Class類型
@NullSource: 表示為參數化測試提供一個null的入參
@EnumSource: 表示為參數化測試提供一個枚舉入參
@CsvFileSource:表示讀取指定CSV文件內容作為參數化測試入參
@MethodSource:表示讀取指定方法的返回值作為參數化測試入參(注意方法返回需要是一個Stream)
當然如果參數化測試僅僅只能做到指定普通的入參還達不到讓我覺得驚艷的地步。讓真正感到他的強大之處的地方在於他可以支持外部的各類入參。如:CSV,YML,JSON 文件甚至方法的返回值也可以作為入參。只需要去實現ArgumentsProvider接口,任何外部文件都可以作為它的入參。
public class ParamTest {
@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("參數化測試1")
public void parameterizedTest1(String string) {
System.out.println(string);
Assertions.assertTrue(StringUtils.isNotBlank(string));
}
@ParameterizedTest
@MethodSource("method") //指定方法名
@DisplayName("方法來源參數")
public void testWithExplicitLocalMethodSource(String name) {
System.out.println(name);
Assertions.assertNotNull(name);
}
static Stream<String> method() {
return Stream.of("apple", "banana");
}
}
遷移指南
Junit4===>Junit5
注解在 org.junit.jupiter.api 包中,斷言在 org.junit.jupiter.api.Assertions 類中,前置條件在 org.junit.jupiter.api.Assumptions 類中。
把@Before 和@After 替換成@BeforeEach 和@AfterEach。
把@BeforeClass 和@AfterClass 替換成@BeforeAll 和@AfterAll。
把@Ignore 替換成@Disabled。
把@Category 替換成@Tag。
把@RunWith、@Rule 和@ClassRule 替換成@ExtendWith。