Why JUnit 5
- JUnit 4 is widely used, but the syntax is cumbersome in many scenarios. JUnit 5 supports lambda expressions, which are simple in syntax and non redundant in code.
- JUnit 5 is easy to expand and inclusive, and can be connected to other test engines.
- More powerful, it provides new assertion mechanism, parametric test, repeatability test and other new functions.
- ps: why should developers test? Is it necessary to write such a standard for single test? In fact, single test is a necessary skill for developers, but many developers' development tasks are too heavy, resulting in no matter after debugging. There is no systematic unit test. Unit test can play a great role in system reconfiguration, and can quickly test whether the new interface is different from that before reconfiguration.
brief introduction

As shown in the figure, JUnit5 structure is as follows:
- JUnit Platform: This is the platform function module provided by Junit. Through it, other test engines can access Junit to realize interface and execution.
- JUnit JUpiter: This is the core of JUnit 5. It is an engine implementation based on JUnit Platform. It contains many rich new features to make automated testing more convenient and powerful.
- JUnit Vintage: This module is a test engine compatible with JUnit 3 and JUnit 4, so that the old version of automated testing can also run normally under JUnit 5.
Dependency introduction
We take Spring Boot2.3.1 As an example, the following dependencies are introduced to prevent the use of the old junit4 related interface. We exclude their dependencies.
I won't introduce the basics of Spring Boot. I recommend the following latest practical tutorial.
https://github.com/javastacks/spring-boot-best-practice
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
Common notes
- @Before each: execute each unit test method before execution
- @Before all: execute once (only once) before the execution of each unit test method
- @DisplayName("commodity warehousing test"): used to specify the name of the unit test
- @Disabled: the current unit test is set to be invalid, that is, the test is skipped during unit test
- @RepeatedTest(n): repeatability test, i.e. n times
- @ParameterizedTest: parameterized test,
- @ValueSource(ints = {1, 2, 3}): provide data for parametric test
Assert
JUnit Jupiter provides a powerful assertion method to verify the results. When using it, we need to take advantage of the new feature of java8, lambda expressions, which are all from org junit. jupiter. api. static method of assertions package.
assertTrue`And`assertFalse`Used to determine whether the condition is`true`or`false @Test @DisplayName("test assertions equals") void testEquals() { assertTrue(3 < 4); }
assertNull and assertNotNull are used to determine whether the condition is · null
@Test @DisplayName("test assertions NotNull") void testNotNull() { assertNotNull(new Object()); }
assertThrows is used to judge whether the exception thrown by the execution meets the expectation, and the exception type can be used to receive the return value for other operations
@Test @DisplayName("Test assertion throw exception") void testThrows() { ArithmeticException arithExcep = assertThrows(ArithmeticException.class, () -> { int m = 5/0; }); assertEquals("/ by zero", arithExcep.getMessage()); }
assertTimeout is used to determine whether the execution process has timed out
@Test @DisplayName("Test assertion timeout") void testTimeOut() { String actualResult = assertTimeout(ofSeconds(2), () -> { Thread.sleep(1000); return "a result"; }); System.out.println(actualResult); }
assertAll is a composite assertion. It passes only after all its internal assertions are executed correctly. Spring Boot series of interview questions and answers have been sorted out, and I am concerned about the official account Java technology stack.
@Test @DisplayName("Test combination assertion") void testAll() { assertAll("test item Order goods", () -> { //Simulated user balance deduction assertTrue(1 < 2, "Sorry, your credit is running low"); }, () -> { //Simulate item database to deduct inventory assertTrue(3 < 4); }, () -> { //Simulated transaction flow database assertNotNull(new Object()); } ); }
Repeatability test
In many scenarios, we need to repeatedly test the same interface method, such as the idempotent interface.
JUnit Jupiter specifies the number of repetitions required by using @ RepeatedTest(n)
@RepeatedTest(3) @DisplayName("Repeat test") void repeatedTest() { System.out.println("call"); }

Parametric test
Parametric tests can run multiple unit tests according to multiple parameters, which is somewhat similar to repetitive tests, except that the parameters passed in each run are not used. need
To use @ ParameterizedTest, you also need @ ValueSource to provide a set of data, which supports eight basic types and String And custom object types, which is extremely convenient to use.
@ParameterizedTest @ValueSource(ints = {1, 2, 3}) @DisplayName("Parametric test") void paramTest(int a) { assertTrue(a > 0 && a < 4); }
Embedded test
@SpringBootTest @AutoConfigureMockMvc @DisplayName("Junit5 unit testing ") public class MockTest { //.... @Nested @DisplayName("Embedded order test") class OrderTestClas { @Test @DisplayName("cancellation of order") void cancelOrder() { int status = -1; System.out.println("Order cancelled successfully,Order status is:"+status); } } }