Spring Boot 2 單元測試


開發環境:IntelliJ IDEA 2019.2.2
Spring Boot版本:2.1.8

IDEA新建一個Spring Boot項目后,pom.xml默認包含了Web應用和單元測試兩個依賴包。
如下:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

一、測試Web服務

1、新建控制器類 HelloController.java

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/")
    public String index() {
        return "index";
    }

    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }
}

2、新建測試類 HelloControllerTest.cs

下面WebEnvironment.RANDOM_PORT會啟動一個真實的Web容器,RANDOM_PORT表示隨機端口,如果想使用固定端口,可配置為
WebEnvironment.DEFINED_PORT,該屬性會讀取項目配置文件(如application.properties)中的端口(server.port)。
如果沒有配置,默認使用8080端口。

package com.example.demo.controller;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void testIndex(){
        String result = restTemplate.getForObject("/",String.class);
        Assert.assertEquals("index", result);
    }

    @Test
    public void testHello(){
        String result = restTemplate.getForObject("/",String.class);
        Assert.assertEquals("Hello world", result);//這里故意寫錯
    }
}

在HelloControllerTest.java代碼中右鍵空白行可選擇Run 'HelloControllerTest',測試類里面所有方法。
(如果只想測試一個方法如testIndex(),可在testIndex()代碼上右鍵選擇Run 'testIndex()')
運行結果如下,一個通過,一個失敗。

二、模擬Web測試

新建測試類 HelloControllerMockTest.java
設置WebEnvironment屬性為WebEnvironment.MOCK,啟動一個模擬的Web容器。
測試方法中使用Spring的MockMvc進行模擬測試。

package com.example.demo.controller;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import java.net.URI;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)//MOCK為默認值,也可不設置
@AutoConfigureMockMvc
public class HelloControllerMockTest {
    @Autowired
    private MockMvc mvc;

    @Test
    public  void testIndex() throws Exception{
        ResultActions ra = mvc.perform(MockMvcRequestBuilders.get(new URI("/")));
        MvcResult result = ra.andReturn();
        System.out.println(result.getResponse().getContentAsString());
    }

    @Test
    public  void testHello() throws Exception{
        ResultActions ra = mvc.perform(MockMvcRequestBuilders.get(new URI("/hello")));
        MvcResult result = ra.andReturn();
        System.out.println(result.getResponse().getContentAsString());
    }
}

右鍵Run 'HelloControllerMockTest',運行結果如下:

三、測試業務組件

1、新建服務類 HelloService.java

package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String hello(){
        return "hello";
    }
}

2、新建測試類 HelloServiceTest.java

WebEnvironment屬性設置為NONE,不會啟動Web容器,只啟動Spring容器。

package com.example.demo.service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class HelloServiceTest {
    @Autowired
    private HelloService helloService;

    @Test
    public void testHello(){
        String result = helloService.hello();
        System.out.println(result);
    }
}

右鍵Run 'HelloServiceTest',運行結果如下:

四、模擬業務組件

假設上面的HelloService.cs是操作數據庫或調用第三方接口,為了不讓這些外部不穩定因素影響單元測試的運行結果,可使用mock來模擬
某些組件的返回結果。
1、新建一個服務類 MainService.java

里面的main方法會調用HelloService的方法

package com.example.demo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MainService {
    @Autowired
    private HelloService helloService;

    public void main(){
        System.out.println("調用業務方法");
        String result = helloService.hello();
        System.out.println("返回結果:" + result);
    }
}

2、新建測試類 MainServiceMockTest.java

下面代碼中,使用MockBean修飾需要模擬的組件helloService,測試方法中使用Mockito的API模擬helloService的hello方法返回。

package com.example.demo.service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MainServiceMockTest {
    @MockBean
    private HelloService helloService;
    @Autowired
    private MainService mainService;

    @Test
    public void testMain(){
        BDDMockito.given(this.helloService.hello()).willReturn("hello world");
        mainService.main();
    }
}

右鍵Run 'MainServiceMockTest',運行結果如下:

五、IDEA項目結構圖

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM