“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.