2021-09-11 SpringBoot integrates Junit5 to make unit testing more elegant - yahya

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.

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

  • 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

The following dependencies are introduced to prevent the use of old junit4 related interfaces. We exclude their dependencies.

<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 powerful assertion methods to verify the results. When using lambda expressions, a new feature of java8, they are static methods from the org.junit.jupiter.api.Assertions package.

assertTrue and assertFalse are 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

@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 (@ RepeatedTest annotation configures the number of automatic repeated calls), such as testing idempotent interfaces.

@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 a bit similar to repetitive tests, except that the parameters passed in each run are different.

You need to use @ ParameterizedTest and @ ValueSource to provide a set of data. It supports eight basic types, String and user-defined 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

JUnit 5 provides the function of nested unit testing, which can better show the business logic relationship between test classes

Usually, a business corresponds to a test class. In fact, classes with business relationships can be written together. This facilitates testing.

Moreover, inline writing can greatly reduce unnecessary classes, simplify projects, prevent class explosion and a series of problems.

@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);
        }
    }
}

Tags: Java unit testing

Posted on Sat, 11 Sep 2021 21:10:16 -0400 by samdennis