springboot+junit测试


参考视频:用Spring Boot编写RESTful API
参考链接:Spring Boot构建RESTful API与单元测试
参考链接:Junit自动单元测试以及测试覆盖率简单使用



一、junit断言

函数 作用
TestCase.assertTrue 判断条件是否为真
TestCase.assertFalse 判断条件是否为假
TestCase.assertEquals(val1,val2) 判断val1是否和val2相等
TestCase.assertNotSame(val1,val2) 判断val1是否和val2不相等
Assert.assertArrayEquals(array1,array2) 判断两个数组相等
TestCase.fail(message) 测试直接失败,抛出message信息

注意:
assertTrue(val1 == val2) 是判断val1和val2是否是同一个实例
assertEquals(val1, val2) 是判断val1和val2值是否相等

Assert中有许多方法被淘汰了,这里建议多用TestCase



二、测试模块

  • 测试模块:我们需要写测试代码的模块
  • 驱动模块:调用我们测试代码的模块
  • 桩模块 :模拟被测试的模块所调用的模块,而不是软件产品的组成的部分,这个桩模块本身不执行任何功能仅在被调用时返回静态值来模拟被调用模块的行为

桩模块简单实例(税收计算较复杂,可以先模仿一下,作为桩模块,这样就可以不影响被测模块的测试):
在这里插入图片描述


三、使用Mockito作为桩模块

我们在maven中加入Mockito和junit的依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <scope>test</scope>
        </dependency>

数据库访问层studentDao如下(还未实现方法):

import org.springframework.stereotype.Repository;
import whu.xsy.swagger_use.entity.student;

import java.util.List;

@Repository
public interface studentDao {

    //TODO 从数据库获取所有学生信息
    List<student> getAll();
}

service层如下(调用studentDao):

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import whu.xsy.swagger_use.dao.studentDao;
import whu.xsy.swagger_use.entity.student;

import java.util.List;


@Service
public class studentService {

    @Autowired
    studentDao studentDao;

    public List<student> getAll(){
        return studentDao.getAll();
    }
}

接下来开始设置桩模块并开始测试

此时数据库并没有数据,数据访问层dao也没写好,那么该如何测试service呢?
我们使用mockito在dao层调用特定方法时模拟返回数据,这样就可以不影响service层的测试,并且即使数据库发生变化(比如环境迁移),也不影响测试。

简而言之,就是mockito接管了dao层

import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
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.SpringJUnit4ClassRunner;
import whu.xsy.swagger_use.dao.studentDao;
import whu.xsy.swagger_use.entity.student;
import whu.xsy.swagger_use.service.studentService;

import java.util.ArrayList;
import java.util.List;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class SwaggerUseApplicationTests {

    @MockBean
    studentDao studentDao;

    @Autowired
    studentService studentService;
    
    @Test
    public void contextLoads(){} // 可用来检测springboot环境

    //测试studentService
    @Test
    public void testStudentService(){
        //模拟数据库中数据
        List<student> students= new ArrayList<>();
        students.add(new student(1,"xsy"));
        students.add(new student(2,"theory"));

        //由于 studentDao 的 getAll() 方法还没写好,所以使用 Mockito 做桩模块,模拟返回数据
        Mockito.when(studentDao.getAll()).thenReturn( students );

        //调用studentService.getAll()
        List<student> result = studentService.getAll();

        //断言
        TestCase.assertEquals(2,result.size());
        TestCase.assertEquals("xsy",result.get(0).getName());
    }
}



四、使用mockMvc测试web层

  1. 在test类上加上 @AutoConfigureMockMvc注解
  2. 自动注入MockMvc mockMvc;
  3. 对studentController中增删改查接口进行测试
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import whu.xsy.swagger_use.entity.student;

import java.util.ArrayList;
import java.util.List;


@RestController
@RequestMapping("/student")
@Api(value = "/student", tags = "学生模块") //标注在类上的
public class studentController {

    //模拟数据库
    private static List<student> students = new ArrayList<>();

    //初始化模拟数据库
    static{
        students.add(new student(1,"xsy"));
        students.add(new student(2,"theory"));
    }

    @GetMapping("")
    public List<student> getAll(){
        return students;
    }


    @PostMapping("")
    public boolean add(student student){
        return students.add(student);
    }

}

测试get方法(期望状态200,返回的json中含有xsy,打印返回的信息)

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
@AutoConfigureMockMvc
public class SwaggerUseApplicationTests {

    @MockBean
    studentDao studentDao;

    @Autowired
    studentService studentService;
    
    @Autowired
    MockMvc mockMvc;
    
    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.standaloneSetup(new studentController()).build();
    }
    @Test
    public void testStudentController() throws Exception {
        RequestBuilder request = null;
        //查询所有学生
        request = get("/student/");
        mockMvc.perform(request)
                .andExpect(status().isOk())
                .andDo(MockMvcResultHandlers.print())
                .andExpect(content().string(Matchers.containsString("xsy")));
    }

}

测试通过,并且打印的信息如下:

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /student/
       Parameters = {}
          Headers = []
             Body = <no character encoding set>
    Session Attrs = {}

Handler:
             Type = whu.xsy.swagger_use.controller.studentController
           Method = whu.xsy.swagger_use.controller.studentController#getAll()

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 type = application/json
             Body = [{"id":1,"name":"xsy"},{"id":2,"name":"theory"}]
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

测试post方法:

本实例中展现了MockMvc如何上传数据和获取返回结果
测试方法与get类似

        request = post("/student/")
                .param("id","3")
                .param("name","ys");
        String result = mockMvc.perform(request)
                .andExpect(status().isOk())
                .andReturn().getResponse().getContentAsString();
        TestCase.assertEquals("true",result);



五、批量测试和测试覆盖率

我们将service的测试和controller的测试分开:
在这里插入图片描述
我们需要一次性运行所有的单元测试,则需要配置一次性运行whu.xsy.swagger_use中的所有test类(具体配置见Junit自动单元测试以及测试覆盖率简单使用
在这里插入图片描述
在这里插入图片描述
然后点击run with coverage
在这里插入图片描述
就可以运行所有的测试文件,并且可以看到覆盖率
在这里插入图片描述

原文地址:https://www.cnblogs.com/theory/p/11884306.html