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

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.cs代码中右键空白行可选择Run ‘HelloControllerTest’,测试类里面所有方法。
(如果只想测试一个方法如testIndex(),可在testIndex()代码上右键选择Run ‘testIndex()’)
运行结果如下,一个通过,一个失败。

《Spring Boot 2 单元测试》

二、模拟Web测试

新建测试类 HelloControllerMockTest.cs
设置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’,运行结果如下:

《Spring Boot 2 单元测试》

三、测试业务组件

1、新建服务类 HelloService.cs

package com.example.demo.service;

import org.springframework.stereotype.Service;

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

2、新建测试类 HelloServiceTest.cs

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’,运行结果如下:

《Spring Boot 2 单元测试》

四、模拟业务组件

假设上面的HelloService.cs是操作数据库或调用第三方接口,为了不让这些外部不稳定因素影响单元测试的运行结果,可使用mock来模拟
某些组件的返回结果。
1、新建一个服务类 MainService.cs

里面的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.cs

下面代码中,使用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’,运行结果如下:

《Spring Boot 2 单元测试》

五、IDEA项目结构图

《Spring Boot 2 单元测试》

 

点赞