“This is the fifth day of my participation in the August More Text Challenge. For more details, see August More Text Challenge

A few things about JUnit

When we develop Web applications, we often test by observing the results directly. Although it is also a way, but not rigorous. Write test code as a developer to test the business logic you write to improve the quality of your code, reduce the probability of error methods, and perform performance tests. Often, as a developer, this is written mostly as unit tests. Introduce the spring-boot-starter-testSpringBoot test dependency. This dependency will be introduced into JUnit’s test package, which is the unit test package we use for many times. Spring Boot has been enhanced to support many aspects of testing, such as JPA, MongoDB, Spring MVC (REST) and Redis.

The next step is mainly to test the code in the business logic layer, REST and Mock tests.

JUnit 1.1 introduction

JUnit is a unit testing framework for the Java language. Founded by Kent Beck and Erich Gamma, it has grown to become the most successful of sUnit’s xUnit family originating from Kent Beck. JUnit has its own JUnit extension ecosystem. Most Java development environments already integrate JUnit as a unit testing tool.

JUnit related concepts meaning
test A @test annotated method defines a Test, runs the method, JUnit creates an instance containing the class, and then calls the annotated method.
The test class A class that contains multiple @test methods
Assert Define the condition you want to test, and the assert method stays silent when the condition is true, and throws an exception when the condition is not
Suite Suite allows you to group test classes into groups
Runner The Runner class is used to run tests. JUnit4 is backward compatible and can run JUnit3 test instances

This is JUnit4.x. JUnit has two important classes: Assume+Assert, and important annotations: BeforeClass, AfterClass, After, Before, Test, and Ignore. BeforeClass and AfterClass are run at the beginning and end of each class and require static decorations. Before and After are run at the beginning and end of each test method.

Code snippets: TestDeployApplication. The class is to write your own Spring Boot startup class.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TestDeployApplication.class})
public class UnitTest1 {

    @BeforeClass
    public static void beforeClass(a) {
        System.out.println("=================BeforeClass================");
    }

    @AfterClass
    public static void afterClass(a) {
        System.out.println("=================AfterClass================");
    }

    @Before
    public void beforeTest(a) {
        System.out.println("before test");
    }

    @After
    public void afterTest(a) {
        System.out.println("after test");
    }

    @Test
    public void test1(a) {
        System.out.println("test1");
    }

    @Test
    public void test2(a) {
        System.out.println("test2"); }}Copy the code

1.2 JUnit Assert class

Common methods in the Assert class:

  • AssertEquals (” messages “,A,B) : When A is determined to be equal to B, an error is thrown if it is not. Comparison objects call equals().
  • AssertSame (” Message “,A,B) : Determines whether the objects are the same.
  • AssertTrue (” Prompt message “,A) : Checks whether condition A is true.
  • AssertFalse (” Info “,A) : Determines whether the condition is false.
  • AssertNotNull (” Message “,A) : Determines whether the object is not empty.
  • AssertNull (” Info “,A) : Determines whether the object is not empty.
  • AssertArrayEqual (” hint “,A,B) : Determines whether arrays A and B are equal.

1.3 the JUnit Suite

JUnit’s Suite is designed to run one or more test cases at a time. A Suite can be thought of as a container for grouping test classes together and running them as a collection. The runner launches the Suite.

@RunWith(Suite.class)
@SuiteClasses({UnitTest1.class,UnitTest2.class})
public class MainTest{}Copy the code

Spring Boot unit tests

Add the required dependencies

<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
Copy the code

2.1 Test scope provided by Spring Boot test dependencies

Spring-boot-starter -test has been introduced to inherit many test libraries:

  • JUnit, the standard unit test Java program.
  • Spring Test and Spring Boot Test, unit tests for Spring Boot applications.
  • Mockito, a Java Mock test framework, is used to simulate any Spring-managed Bean. For example, in a unit test, the data returned by a third-party system interface is simulated without actually requesting the third-party interface.
  • AssertJ, an Assertion library, also provides more ways to compare expected values with test returns.
  • Hamcrest, the matching object for the library.
  • JSONassert, a library for asserting JSON objects or JSON strings.
  • JSONPath, which provides an xPath-like notation to get JSON fields.

2.2 Scaffolding for Spring Boot unit tests

In a Spring Boot project created using Spring. IO, a unit tested class is common by default.

@RunWith(SpringRunner.class)
@SpringBootTest
public class UnitTest1 {
	@Test
    public void contextLoads(a){}}Copy the code

RunWith is an annotation in JUnit that tells the JUnit unit testing framework not to use the built-in method for unit testing. Above, it specifies the use of the SpringRunner class to provide unit tests.

The @SpringBooTtest annotations are used to test the SpringBoot application. By default, the branch will register to look up the SpringBoot main program, which is called @SpringBootApplocation annotations. And start the class when the unit tests are started to create the Spring context. So when we unit test the Spring Boot application, we can see the Spring Boot application startup log in the log output.

2.3 Testing Service layer code

import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class ServiceUnitTest {

    @MockBean
    private ThirdSystemService thirdSystemService;

    @Autowired
    private ISysUserService userService;

    @Test
    public void test1(a) {
        Long expectResult = 100L; given(thirdSystemService.develop()).willReturn(expectResult); SysUser sysUser = userService.findById(expectResult); System.out.println(sysUser.toString()); }}Copy the code

MockBean retrieves the beans managed above under Spring, but the thirdSystemService Bean is not actually an actual column, but a test instance created with the Mockito tool. Using the @MockBean annotation, a Bean that calls a method without actually calling a method can be used on a system that relies on a third party. However, the connection to the third party system is not complete, and you can test your own business code separately. WillReturn (expectResult) indicates that the result always returns 100L.

2.5 Testing the MVC code

It is also possible to test Controller code separately in Spring Boot, for example to test logic such as parameter binding and validation for methods in the Controller. Unit testing can be done through the @webMvcTest annotation.

@RunWith(SpringRunner.class)
@WebMvcTest(SysUserController.class)
public class ServiceUnitTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test2(a) throws Exception {
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/hello/{id}".1L);
        mockMvc.perform(requestBuilder)
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andDo(MockMvcResultHandlers.print());
    }
}
Copy the code

Pass parameters like the Get method

MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders
       .get("/hello/{id}".1L)   / / the path variable
       .param("name"."hello");  // @requestparam gets the variable. Post requests also apply
Copy the code

File upload

@RunWith(SpringRunner.class)
@WebMvcTest(SysUserController.class)
public class ServiceUnitTest {

   @Autowired
   private MockMvc mockMvc;

   @Test
   public void test3(a) throws Exception {
       // Get the file
       FileInputStream fileInputStream = new FileInputStream("File path");
       // Build the file upload object
       MockMultipartFile mockMultipartFile = new MockMultipartFile("file", fileInputStream);
       // Build the mock file upload request
       MockMultipartHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.multipart("/upload").file(mockMultipartFile);
       // Send the request
       mockMvc.perform(requestBuilder)
               .andExpect(MockMvcResultMatchers.status().isOk())
               .andDo(MockMvcResultHandlers.print());
   }
}
Copy the code

Simulate cookies and sessions

@RunWith(SpringRunner.class)
@WebMvcTest(SysUserController.class)
public class ServiceUnitTest {

   @Autowired
   private MockMvc mockMvc;

   @Test
   public void test4(a) throws Exception {
       MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders
               .get("index.html")
               .sessionAttr("name"."hello")
               .cookie(new Cookie("token"."123345"));
       mockMvc.perform(requestBuilder)
               .andExpect(MockMvcResultMatchers.status().isOk())
               .andDo(MockMvcResultHandlers.print());

   }
}
Copy the code

Setting the request header

@RunWith(SpringRunner.class)
@WebMvcTest(SysUserController.class)
public class ServiceUnitTest {

   @Autowired
   private MockMvc mockMvc;

   @Test
   public void test5(a) throws Exception {
       MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders
               .get("index.html")
               .content(MediaType.APPLICATION_JSON_VALUE) // The expected return type
               .contentType(MediaType.APPLICATION_JSON_VALUE) // The type of content to be submitted
               .header("token".1235); // Set the request header
       mockMvc.perform(requestBuilder)
               .andExpect(MockMvcResultMatchers.status().isOk())
               .andDo(MockMvcResultHandlers.print());

   }
}
Copy the code

2.6 Compare the returned results

The MockMvc class’s Perform method returns a ResultAction class that can perform some operations on the results (andExpect, andDo, andReturn).

@RunWith(SpringRunner.class)
@WebMvcTest(SysUserController.class)
public class ServiceUnitTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test2(a) throws Exception {
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders
                .get("/hello/{id}".1L)
                .param("name"."hello");

        mockMvc.perform(requestBuilder)
                .andExpect(MockMvcResultMatchers.jsonPath("$.id"."id").value(2L)); .andDo(MockMvcResultHandlers.print()); }}Copy the code

For example, the above test gets the value of the ID field in the returned JSON result. Value is the expected value. If the expected value is different from the actual value, the test will report an error.

You can also assert whether the View and Model that the test returns are expected values

@RunWith(SpringRunner.class)
@WebMvcTest(SysUserController.class)
public class ServiceUnitTest {

    @Autowired
    private MockMvc mockMvc;

    MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders
                .get("/hello/{id}".1L)
                .param("name"."hello");

        mockMvc.perform(requestBuilder)
            	// Assert an attempt to return
                .andExpect(MockMvcResultMatchers.view().name("index.html"))
            	// Assert the data in the returned data model
                .andExpect(MockMvcResultMatchers.model().attribute("id".1L))
                .andDo(MockMvcResultHandlers.print());
}
Copy the code

More result assertions can be found in the MockMvcResultMatchers class, which is a utility class that requests matches for results.