一、springboot2 中的 Junit5 使用
對于service層測試,Junit5中隻需要@SpringBootTest即可,不需要額外Mockmvc
Springboot 整合 Junit 以後
編寫測試方法:@Test标注(注意需要使用 junit5 版本的注解)
Junit類具有 Spring 的功能, 例如 @Autowired、@Transactional (标注測試方法,測試完成後自動回)
我們隻需要引入 spring-boot-starter-test 依賴即可完成整合,其它的 Springboot 底層都已經幫我們自動配置好了
使用最新的springboot的版本, 使用的是junit5版本, 現在很多都是使用junit4的測試, 這裡使用Junit5來試驗. junit4和junit5兩個版本差别比較大。

junit5基于java8寫的,要求最低版本為java8。
預言使用:
Assertions.assertEquals("index", result);
使用ideal建構springboot項目,pom.xml(部分) 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!--加入下面的引入,可以使用junit5的版本來測試; 如果想用junit4的測試, 把exclusioins去除-->
<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>
</dependencies>
</project>
建立一個controller
package com.test.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/index")
public class IndexController {
private static final Logger LOG = LoggerFactory.getLogger(IndexController.class);
@RequestMapping(value="/getData")
@ResponseBody
public String getData(@RequestParam(value="searchPhrase", required=false) String searchPhrase) {
String status = "{\"status\" : \"200\", \"searchPhrase\" : \"" + searchPhrase + "\"}";
return status;
}
}
建立一個測試類:
package com.test.demo;
import com.test.demo.controller.IndexController;
import org.junit.jupiter.api.*; //注意這裡, 這是junit5引入的; junit4引入的是org.junit.Test這樣類似的包
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
//這裡隻寫SpringBootTest這個注解; 如果是junit4的話, 就要加上@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests {
private static final Logger LOG = LoggerFactory.getLogger(DemoApplicationTests.class);
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Test
void contextLoads() {
}
@BeforeAll
public static void beforeAll(){
LOG.info("beforeAll");
}
@BeforeEach
public void beforeEach(){
LOG.info("beforeEach"); //mockMvc = MockMvcBuilders.standaloneSetup(new IndexController()).build();
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@AfterEach
public void afterEach(){
LOG.info("afterEach");
}
@AfterAll
public static void afterAll(){
LOG.info("afterAll");
}
@Test
public void testTwo() throws Exception {
RequestBuilder request = MockMvcRequestBuilders.get("/index/getData")
.param("searchPhrase","ABC") //傳參
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON); //請求類型 JSON
MvcResult mvcResult = mockMvc.perform(request)
.andExpect(MockMvcResultMatchers.status().isOk()) //期望的結果狀态 200
.andDo(MockMvcResultHandlers.print()) //添加ResultHandler結果處理器,比如調試時 列印結果(print方法)到控制台
.andReturn(); //傳回驗證成功後的MvcResult;用于自定義驗證/下一步的異步處理;
int status = mvcResult.getResponse().getStatus(); //得到傳回代碼
String content = mvcResult.getResponse().getContentAsString(); //得到傳回結果
LOG.info("status:" + status + ",content:" + content);
}
}
最後進行測試:
進入自己的目錄, 這裡我是通過指令運作的, 也可以通過其他方式運作(如ide的環境)
cd xxx/Demo>mvn test
測試結果如下:
2020-04-11 13:04:49.920 [main] INFO com.test.demo.DemoApplicationTests - beforeAll 2020-04-11 13:04:55.239 [main] com.test.demo.DemoApplicationTests: beforeEach MockHttpServletRequest: HTTP Method = GET Request URI = /index/getData Parameters = {searchPhrase=[ABC]} Headers = [Content-Type:"application/json", Accept:"application/json"] Body = <no character encoding set> Session Attrs = {} Handler: Type = com.test.demo.controller.IndexController Method = com.test.demo.controller.IndexController#getData(String) Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200 Error message = null Headers = [Content-Type:"application/json", Content-Length:"42"] Content type = application/json Body = {"status" : "200", "searchPhrase" : "ABC"} Forwarded URL = null Redirected URL = null Cookies = [] 2020-04-11 13:04:55.395 INFO 13164 --- [main] com.test.demo.DemoApplicationTests: status:200,content:{"status" : "200", "searchPhrase" : "ABC"}
2020-04-11 13:04:56.002 INFO 13164 --- [main] com.test.demo.DemoApplicationTests: afterEach
2020-04-11 13:04:56.009 INFO 13164 --- [main] com.test.demo.DemoApplicationTests: afterAll
這裡可以看到傳回的結果status:200,content:{"status" : "200", "searchPhrase" : "ABC"}
其中傳入的參數是ABC!!!