天天看點

SpringBoot單元測試Test Junit4和Junit5一、springboot2 中的 Junit5 使用

一、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兩個版本差别比較大。

SpringBoot單元測試Test Junit4和Junit5一、springboot2 中的 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!!!