Junit5 introduction and common test notes
Spring boot has introduced JUnit 5 as the default library for unit testing since version 2.2.0. However, starting with versions above 2.4, the default dependency on Vintage (that is, modules compatible with JUnit 4 and JUnit 3) has been removed. If we need to be compatible with JUnit 4, we need to manually add JUnit 4 dependencies.
Next, let's introduce JUnit 5 and its common test annotations.
1. Introduction to Junit5
Junit5 is very different from the previous version, mainly composed of several different modules of three different subprojects. Here's a formula:
Junit5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
- JUnit platform: JUnit platform is the basis for starting the test framework on the JVM. It supports not only JUnit's self-made test engine, but also other test engines.
- JUnit Jupiter: JUnit Jupiter provides a new programming model for JUnit 5 and is the core of JUnit 5's new features. A test engine is included internally to run on the JUnit Platform.
- JUnit Vintage: since JUnit has been developed for many years, in order to take care of old projects, JUnit Vintage provides a test engine compatible with JUnit 4 and JUnit 3.
To introduce JUnit 5 dependencies, we just need to import its starter (scenario).
<!--test--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
If we use springboot 2.4 and later versions to be compatible with Junit4 and Junit3, we have to add another dependency as follows:
<!--SpringBoot2.4 Start, compatible Junit4 Manual import required Vintage--> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency>
After integrating Junit5 with SpringBoot:
1. Write the test method: just use the @ test tag (note that the path of the @ test package is org.junit.jupiter.api.Test)
2. Junit class has the functions of Spring and Java, and can be automatically injected using @ Autowired and @ Resource.
3. For some test methods that need to be rolled back, we can add @ Transactional annotation to make the test method roll back automatically after execution.
2. Junit5 common test notes
annotation | describe |
---|---|
@Test | The presentation method is a test method. Unlike Junit4, it cannot declare any properties |
@ParameterizedTest | The representation method is parametric testing |
@RepeatedTest | The representation method is repeatable |
@DisplayName | Set the presentation name for the test class or method |
@BeforeEach | Indicates that it is executed before each unit test (several tests are executed several times) |
@AfterEach | Indicates that it is executed after each unit test (several tests are executed several times) |
@BeforeAll | Means to execute before all unit tests (no matter how many tests are executed only once) |
@AfterAll | Indicates that it is executed after all unit tests (no matter how many tests are executed, it is only executed once) |
@Tag | Represents the unit test category, similar to Junit4's @ Categories |
@Disabled | Indicates that the test class or test method is not executed, similar to @ Ignore in Junit4 |
@Timeout | Indicates that the test method will return an error if it exceeds the specified time |
@ExtendWith | Provide an extension class reference for a test class or test method |
1. DispalyName annotation:
Case: name the test class and method.
package com.example.boot; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("Just a test class with a name") public class MyTest { @DisplayName("This is a method with a name") @Test public void testDisplayName(){ System.out.println("test DisplayName"); } }
result:
2. BeforeEach and AfterEach annotations
Case: output a sentence before and after each test method.
package com.example.boot; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("Just a test class with a name") public class MyTest { @DisplayName("This is a method with a name") @Test public void testDisplayName(){ System.out.println("test DisplayName"); } @BeforeEach public void testBeforeEach(){ System.out.println("BeforeEach-------------"); } @AfterEach public void testAfterEach(){ System.out.println("AfterEach--------------"); } }
result:
3. BeforeAll and AfterAll annotations
Note: BeforeAll and AfterAll are executed before all test methods are executed, which means that they are only executed once in total. Therefore, the direct methods using BeforeAll and AfterAll are either static or have to add the rollback annotation @ Transactional. Otherwise, an error will be reported.
A class that runs the following methods, that is, executes all test methods.
package com.example.boot; import org.junit.jupiter.api.*; @DisplayName("Just a test class with a name") public class MyTest { @DisplayName("This is a method with a name") @Test public void testDisplayName(){ System.out.println("test DisplayName"); } @DisplayName("This is the second method with a name") @Test public void testDisplayName_2(){ System.out.println("Fell in love with naming the method"); } @BeforeEach public void testBeforeEach(){ System.out.println("BeforeEach-------------"); } @AfterEach public void testAfterEach(){ System.out.println("AfterEach--------------"); } @BeforeAll public static void testBeforeAll(){ System.out.println("BeforeAll---------------------"); } @AfterAll public static void testAfterAll(){ System.out.println("AfterAll----------------------"); } }
Results: (BeforeEach and AfterEach are executed before and after each test method, and BeforeAll and AfterAll are executed only once at the front and back)
4. @ Disable annotation
Now, we don't want to run the second test method, so we can add the @ Disable annotation to the second test method, so that when we run our test class, we won't run that test method.
Result: (also told us that the method has @ Disable annotation, which is humanized!!!)
5. @ TimeOut annotation
If the program runs for more than the specified time, it will automatically report an error.
The first parameter is a value and the second parameter is a unit. (there are days, hours, minutes, seconds, milliseconds, etc.)
@Timeout(value = 500,unit = TimeUnit.MILLISECONDS) @Test public void testTimeout() throws InterruptedException { Thread.sleep(600); }
result:
Unit of the second parameter:
6. @ ExtendWith annotation
This annotation is great. If we do not use the @ SpringBootTest annotation, we cannot use our @ AutoWired annotation in this test class. The reason why it can be used is that the @ SpringBootTest annotation extends a series of annotations about Spring (of course, the above sentence @ bootstrap with is also useful):
7. @ RepeatedTest annotation*
@The RepeatedTest annotation repeats the test.
@RepeatedTest(3) @Test public void testRepeated(){ System.out.println("Run!!!"); }
After a try, he seems to run once and then repeat it three times.
The results are as follows: (once above, three times below)