JUnit5 快速指南
生活随笔
收集整理的這篇文章主要介紹了
JUnit5 快速指南
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
JUnit5 快速指南
version: junit5
- 1. 安裝
- 2. JUnit 注解
- 3. 編寫單元測試
- 3.1. 基本的單元測試類和方法
- 3.2. 定制測試類和方法的顯示名稱
- 3.3. 斷言(Assertions)
- 3.4. 假想(Assumptions)
- 3.5. 禁用
- 3.6. 測試條件
- 3.7. 嵌套測試
- 3.8. 重復測試
- 3.9. 參數化測試
- 4. 引用和引申
1. 安裝
在 pom 中添加依賴
<properties><junit.jupiter.version>5.3.2</junit.jupiter.version> </properties><dependencies><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>${junit.jupiter.version}</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>${junit.jupiter.version}</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>${junit.jupiter.version}</version><scope>test</scope></dependency> </dependencies>組件間依賴關系:
2. JUnit 注解
| @Test | Denotes that a method is a test method. Unlike JUnit 4’s @Test annotation, this annotation does not declare any attributes, since test extensions in JUnit Jupiter operate based on their own dedicated annotations. Such methods are inherited unless they are overridden. |
| @ParameterizedTest | Denotes that a method is a parameterized test. Such methods are inherited unless they are overridden. |
| @RepeatedTest | Denotes that a method is a test template for a repeated test. Such methods are inherited unless they are overridden. |
| @TestFactory | Denotes that a method is a test factory for dynamic tests. Such methods are inherited unless they are overridden. |
| @TestInstance | Used to configure the test instance lifecycle for the annotated test class. Such annotations are inherited. |
| @TestTemplate | Denotes that a method is a template for test cases designed to be invoked multiple times depending on the number of invocation contexts returned by the registered providers. Such methods are inherited unless they are overridden. |
| @DisplayName | Declares a custom display name for the test class or test method. Such annotations are not inherited. |
| @BeforeEach | Denotes that the annotated method should be executed before each @Test, @RepeatedTest, @ParameterizedTest, or @TestFactory method in the current class; analogous to JUnit 4’s @Before. Such methods are inherited unless they are overridden. |
| @AfterEach | Denotes that the annotated method should be executed after each @Test, @RepeatedTest, @ParameterizedTest, or @TestFactory method in the current class; analogous to JUnit 4’s @After. Such methods are inherited unless they are overridden. |
| @BeforeAll | Denotes that the annotated method should be executed before all @Test, @RepeatedTest, @ParameterizedTest, and @TestFactory methods in the current class; analogous to JUnit 4’s @BeforeClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the "per-class" test instance lifecycle is used). |
| @AfterAll | Denotes that the annotated method should be executed after all @Test, @RepeatedTest, @ParameterizedTest, and @TestFactory methods in the current class; analogous to JUnit 4’s @AfterClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the "per-class" test instance lifecycle is used). |
| @Nested | Denotes that the annotated class is a nested, non-static test class. @BeforeAll and @AfterAllmethods cannot be used directly in a @Nested test class unless the "per-class" test instance lifecycle is used. Such annotations are not inherited. |
| @Tag | Used to declare tags for filtering tests, either at the class or method level; analogous to test groups in TestNG or Categories in JUnit 4. Such annotations are inherited at the class level but not at the method level. |
| @Disabled | Used to disable a test class or test method; analogous to JUnit 4’s @Ignore. Such annotations are not inherited. |
| @ExtendWith | Used to register custom extensions. Such annotations are inherited. |
3. 編寫單元測試
3.1. 基本的單元測試類和方法
import org.junit.jupiter.api.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory;class Junit5StandardTests {private static final Logger LOGGER = LoggerFactory.getLogger(Junit5StandardTests.class);@BeforeAllstatic void beforeAll() {LOGGER.info("call beforeAll()");}@BeforeEachvoid beforeEach() {LOGGER.info("call beforeEach()");}@Testvoid succeedingTest() {LOGGER.info("call succeedingTest()");}@Testvoid failingTest() {LOGGER.info("call failingTest()");// fail("a failing test");}@Test@Disabled("for demonstration purposes")void skippedTest() {LOGGER.info("call skippedTest()");// not executed}@AfterEachvoid afterEach() {LOGGER.info("call afterEach()");}@AfterAllstatic void afterAll() {LOGGER.info("call afterAll()");} }3.2. 定制測試類和方法的顯示名稱
支持普通字符、特殊符號、emoji
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test;@DisplayName("A special test case") class JunitDisplayNameDemo {@Test@DisplayName("Custom test name containing spaces")void testWithDisplayNameContainingSpaces() { }@Test@DisplayName("╯°□°)╯")void testWithDisplayNameContainingSpecialCharacters() { }@Test@DisplayName("?")void testWithDisplayNameContainingEmoji() { } }3.3. 斷言(Assertions)
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test;import static java.time.Duration.ofMillis; import static java.time.Duration.ofMinutes; import static org.junit.jupiter.api.Assertions.*;class AssertionsDemo {private static Person person;@BeforeAllpublic static void beforeAll() {person = new Person("John", "Doe");}@Testvoid standardAssertions() {assertEquals(2, 2);assertEquals(4, 4, "The optional assertion message is now the last parameter.");assertTrue('a' < 'b', () -> "Assertion messages can be lazily evaluated -- "+ "to avoid constructing complex messages unnecessarily.");}@Testvoid groupedAssertions() {// In a grouped assertion all assertions are executed, and any// failures will be reported together.assertAll("person", () -> assertEquals("John", person.getFirstName()),() -> assertEquals("Doe", person.getLastName()));}@Testvoid dependentAssertions() {// Within a code block, if an assertion fails the// subsequent code in the same block will be skipped.assertAll("properties", () -> {String firstName = person.getFirstName();assertNotNull(firstName);// Executed only if the previous assertion is valid.assertAll("first name", () -> assertTrue(firstName.startsWith("J")),() -> assertTrue(firstName.endsWith("n")));}, () -> {// Grouped assertion, so processed independently// of results of first name assertions.String lastName = person.getLastName();assertNotNull(lastName);// Executed only if the previous assertion is valid.assertAll("last name", () -> assertTrue(lastName.startsWith("D")),() -> assertTrue(lastName.endsWith("e")));});}@Testvoid exceptionTesting() {Throwable exception = assertThrows(IllegalArgumentException.class, () -> {throw new IllegalArgumentException("a message");});assertEquals("a message", exception.getMessage());}@Testvoid timeoutNotExceeded() {// The following assertion succeeds.assertTimeout(ofMinutes(2), () -> {// Perform task that takes less than 2 minutes.});}@Testvoid timeoutNotExceededWithResult() {// The following assertion succeeds, and returns the supplied object.String actualResult = assertTimeout(ofMinutes(2), () -> {return "a result";});assertEquals("a result", actualResult);}@Testvoid timeoutNotExceededWithMethod() {// The following assertion invokes a method reference and returns an object.String actualGreeting = assertTimeout(ofMinutes(2), AssertionsDemo::greeting);assertEquals("Hello, World!", actualGreeting);}@Testvoid timeoutExceeded() {// The following assertion fails with an error message similar to:// execution exceeded timeout of 10 ms by 91 msassertTimeout(ofMillis(10), () -> {// Simulate task that takes more than 10 ms.Thread.sleep(100);});}@Testvoid timeoutExceededWithPreemptiveTermination() {// The following assertion fails with an error message similar to:// execution timed out after 10 msassertTimeoutPreemptively(ofMillis(10), () -> {// Simulate task that takes more than 10 ms.Thread.sleep(100);});}private static String greeting() {return "Hello, World!";}}3.4. 假想(Assumptions)
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.Assumptions.assumingThat;import org.junit.jupiter.api.Test;class AssumptionsDemo {@Testvoid testOnlyOnCiServer() {assumeTrue("CI".equals(System.getenv("ENV")));// remainder of test}@Testvoid testOnlyOnDeveloperWorkstation() {assumeTrue("DEV".equals(System.getenv("ENV")),() -> "Aborting test: not on developer workstation");// remainder of test}@Testvoid testInAllEnvironments() {assumingThat("CI".equals(System.getenv("ENV")),() -> {// perform these assertions only on the CI serverassertEquals(2, 2);});// perform these assertions in all environmentsassertEquals("a string", "a string");}}3.5. 禁用
禁用單元測試類示例:
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test;@Disabled class DisabledClassDemo {@Testvoid testWillBeSkipped() {} }禁用單元測試方法示例:
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test;class DisabledTestsDemo {@Disabled@Testvoid testWillBeSkipped() {}@Testvoid testWillBeExecuted() {} }3.6. 測試條件
操作系統條件
@Test @EnabledOnOs(MAC) void onlyOnMacOs() {// ... }@TestOnMac void testOnMac() {// ... }@Test @EnabledOnOs({ LINUX, MAC }) void onLinuxOrMac() {// ... }@Test @DisabledOnOs(WINDOWS) void notOnWindows() {// ... }@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Test @EnabledOnOs(MAC) @interface TestOnMac { }Java 運行時版本條件
@Test @EnabledOnJre(JAVA_8) void onlyOnJava8() {// ... }@Test @EnabledOnJre({ JAVA_9, JAVA_10 }) void onJava9Or10() {// ... }@Test @DisabledOnJre(JAVA_9) void notOnJava9() {// ... }系統屬性條件
@Test @EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*") void onlyOn64BitArchitectures() {// ... }@Test @DisabledIfSystemProperty(named = "ci-server", matches = "true") void notOnCiServer() {// ... }3.7. 嵌套測試
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue;import java.util.EmptyStackException; import java.util.Stack;import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test;@DisplayName("A stack") class TestingAStackDemo {Stack<Object> stack;@Test@DisplayName("is instantiated with new Stack()")void isInstantiatedWithNew() {new Stack<>();}@Nested@DisplayName("when new")class WhenNew {@BeforeEachvoid 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";@BeforeEachvoid 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());}}} }3.8. 重復測試
import static org.junit.jupiter.api.Assertions.assertEquals;import java.util.logging.Logger;import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.RepetitionInfo; import org.junit.jupiter.api.TestInfo;class RepeatedTestsDemo {private Logger logger = // ...@BeforeEachvoid beforeEach(TestInfo testInfo, RepetitionInfo repetitionInfo) {int currentRepetition = repetitionInfo.getCurrentRepetition();int totalRepetitions = repetitionInfo.getTotalRepetitions();String methodName = testInfo.getTestMethod().get().getName();logger.info(String.format("About to execute repetition %d of %d for %s", //currentRepetition, totalRepetitions, methodName));}@RepeatedTest(10)void repeatedTest() {// ...}@RepeatedTest(5)void repeatedTestWithRepetitionInfo(RepetitionInfo repetitionInfo) {assertEquals(5, repetitionInfo.getTotalRepetitions());}@RepeatedTest(value = 1, name = "{displayName} {currentRepetition}/{totalRepetitions}")@DisplayName("Repeat!")void customDisplayName(TestInfo testInfo) {assertEquals(testInfo.getDisplayName(), "Repeat! 1/1");}@RepeatedTest(value = 1, name = RepeatedTest.LONG_DISPLAY_NAME)@DisplayName("Details...")void customDisplayNameWithLongPattern(TestInfo testInfo) {assertEquals(testInfo.getDisplayName(), "Details... :: repetition 1 of 1");}@RepeatedTest(value = 5, name = "Wiederholung {currentRepetition} von {totalRepetitions}")void repeatedTestInGerman() {// ...}}3.9. 參數化測試
@ParameterizedTest @ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" }) void palindromes(String candidate) {assertTrue(isPalindrome(candidate)); }4. 引用和引申
- Github
- 官方用戶手冊
- Javadoc
- 版本聲明
- 官方示例
轉載于:https://www.cnblogs.com/jingmoxukong/p/10162245.html
總結
以上是生活随笔為你收集整理的JUnit5 快速指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Faiss优化:针对OMP_NUM_TH
- 下一篇: keepalived实现nginx的高可