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 beforeeach@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 aftereach@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 beforeall@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 afterall@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.
@BeforeAll publicstaticvoidbeforeAll() { person = newPerson("John", "Doe"); }
@Test voidstandardAssertions() { 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."); }
@Test voidgroupedAssertions() { // 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())); }
@Test voiddependentAssertions() { // Within a code block, if an assertion fails the // subsequent code in the same block will be skipped. assertAll("properties", () -> { StringfirstName= 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. StringlastName= person.getLastName(); assertNotNull(lastName);
// Executed only if the previous assertion is valid. assertAll("last name", () -> assertTrue(lastName.startsWith("D")), () -> assertTrue(lastName.endsWith("e"))); }); }
@Test voidtimeoutNotExceeded() { // The following assertion succeeds. assertTimeout(ofMinutes(2), () -> { // Perform task that takes less than 2 minutes. }); }
@Test voidtimeoutNotExceededWithResult() { // The following assertion succeeds, and returns the supplied object. StringactualResult= assertTimeout(ofMinutes(2), () -> { return"a result"; }); assertEquals("a result", actualResult); }
@Test voidtimeoutNotExceededWithMethod() { // The following assertion invokes a method reference and returns an object. StringactualGreeting= assertTimeout(ofMinutes(2), AssertionsDemo::greeting); assertEquals("Hello, World!", actualGreeting); }
@Test voidtimeoutExceeded() { // The following assertion fails with an error message similar to: // execution exceeded timeout of 10 ms by 91 ms assertTimeout(ofMillis(10), () -> { // Simulate task that takes more than 10 ms. Thread.sleep(100); }); }
@Test voidtimeoutExceededWithPreemptiveTermination() { // The following assertion fails with an error message similar to: // execution timed out after 10 ms assertTimeoutPreemptively(ofMillis(10), () -> { // Simulate task that takes more than 10 ms. Thread.sleep(100); }); }
@Test voidtestOnlyOnCiServer() { assumeTrue("CI".equals(System.getenv("ENV"))); // remainder of test }
@Test voidtestOnlyOnDeveloperWorkstation() { assumeTrue("DEV".equals(System.getenv("ENV")), () -> "Aborting test: not on developer workstation"); // remainder of test }
@Test voidtestInAllEnvironments() { assumingThat("CI".equals(System.getenv("ENV")), () -> { // perform these assertions only on the CI server assertEquals(2, 2); });
// perform these assertions in all environments assertEquals("a string", "a string"); }
@Test @DisplayName("it is no longer empty") voidisNotEmpty() { assertFalse(stack.isEmpty()); }
@Test @DisplayName("returns the element when popped and is empty") voidreturnElementWhenPopped() { assertEquals(anElement, stack.pop()); assertTrue(stack.isEmpty()); }
@Test @DisplayName("returns the element when peeked but remains not empty") voidreturnElementWhenPeeked() { assertEquals(anElement, stack.peek()); assertFalse(stack.isEmpty()); } } } }
@RepeatedTest(value = 1, name = RepeatedTest.LONG_DISPLAY_NAME) @DisplayName("Details...") voidcustomDisplayNameWithLongPattern(TestInfo testInfo) { assertEquals(testInfo.getDisplayName(), "Details... :: repetition 1 of 1"); }
@RepeatedTest(value = 5, name = "Wiederholung {currentRepetition} von {totalRepetitions}") voidrepeatedTestInGerman() { // ... }
}
参数化测试
1 2 3 4 5
@ParameterizedTest @ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" }) voidpalindromes(String candidate) { assertTrue(isPalindrome(candidate)); }
// 其他用来验证函数是否被调用的方法 verify(mock, never()).someMethod("never called"); verify(mock, atLeastOnce()).someMethod("called at least once"); verify(mock, atLeast(2)).someMethod("called at least twice"); verify(mock, times(5)).someMethod("called five times"); verify(mock, atMost(3)).someMethod("called at most 3 times"); }
Result "io.github.dunwu.javatech.jmh.StringBuilderBenchmark.testStringBuilderAdd": 84487.902 ±(99.9%) 4355.525 ops/ms [Average] (min, avg, max) = (72316.121, 84487.902, 89388.624), stdev = 5015.829 CI (99.9%): [80132.377, 88843.427] (assumes normal distribution) # Run complete. Total time: 00:05:23
REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial experiments, perform baseline and negative tests that provide experimental control, make sure the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts. Do not assume the numbers tell you what you want them to tell.
//scan urls that contain 'my.package', include inputs starting with 'my.package', use the default scanners Reflectionsreflections=newReflections("my.package");
//or using ConfigurationBuilder newReflections(newConfigurationBuilder() .setUrls(ClasspathHelper.forPackage("my.project.prefix")) .setScanners(newSubTypesScanner(), newTypeAnnotationsScanner().filterResultsBy(optionalFilter), ...), .filterInputsBy(newFilterBuilder().includePackage("my.project.prefix")) ...);