SpringBootTest单元测试应用

本文详细介绍SpringBoot项目中如何进行单元测试,包括Service层和服务接口的测试方法,并演示如何使用MockMvc进行Controller层的测试。

    前言:

    为什么需要使用单元测试???

  •    保证历史版本代码的正确性,减少重复测试:开发人员实现某个功能或者修补了某个bug,如果有相应的单元测试支持的话,开发人员可以马上通过运行单元测试来验证之前完成的代码是否正确;
  •    提升测试效率:对于依赖多,业务流程复杂,可以通过mock去掉依赖,保证自己编写函数的正确性;
  •    便于后期重构:保单元测试可以为代码的重构提供保障,只要重构代码之后单元测试全部运行通过,那么在很大程度上表示这次重构没有引入新的BUG,当然这是建立在完整、有效的单元测试覆盖率的基础上;
  •    对设计的反馈:单元测试可以反过来指导设计出高内聚、低耦合的模块;   持续集成的一个前提,保证。  

    -- 下面中介绍Spring Boot项目中的单元测试  

目录

  Junit+SpringBootTest单元测试

Service层单元测试

创建测试类:

编写创建好的测试类,具体代码如下:

Controller单元测试

新断言assertThat使用

assertThat 的基本语法如下:

assertThat 的优点

如何使用 assertThat

单元测试回滚

修改默认引擎的步骤


  Junit+SpringBootTest单元测试

   Spring Boot中引入单元测试很简单,依赖如下:

 dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-test'
}

  引入spring-boot-starter-test后,有如下几个库:

•JUnit - 一个Java语言的单元测试框架。

•Spring Test&Spring Boot Test - 单元和用于系统的集成测试。

•AssertJ - 一个流畅的断言库。 •Hamcrest - matcher对象库(也称为约束或谓词),可以帮助我们创建匹配器对象。

•Mockito - 是一个针对Java的mocking框架。它与EasyMock和jMock很相似,但是通过在执行后校验什么已经被调用,它消除了对期望行为(expectations)的需要。

 •JSONassert - JSON的断言库。 •JsonPath - 用于JSON的XPath。

Service层单元测试

创建测试类:

1、鼠标自动生成

Spring Boot中单元测试类写在在src/test/java目录下,你可以手动创建具体测试类,如果是IDEA,则可以通过IDEA自动创建测试类,如下图:

自动生成测试类如下:

 

2、Alt+Insert快捷键,选择Test...快速生成单元测试类

快速生成Junit单元测试技巧。

Alt+Insert呼出Generate界面,选择Test...,呼出右侧界面,其中①处可以选择单元测试所使用的框架或者二类库,②可以指定该类对应的单元测试类名称,③可以指定该单元测试类继承的父类,一般都是统一继承一个父类,父类里面写单元测试的注解、资源初始化、mock登录、资源释放等操作,④处指定生成的单元测试类包全路径,⑤处可以选择是否生成setUp和tearDown方法,一般③处继承父类就不需要勾选了,⑥处指定生成哪些方法的单元测试方法。

编写创建好的测试类,具体代码如下:

 

@RunWith(SpringRunner.class) // 表明执行程序用spring自己的执行机
@SpringBootTest //表明这是一个springboot测试类,会自动加载springboot主启动程序
public class GsCodeServiceImplTest {
    @Autowired
    GsCodeServiceImpl codeService;
    @Test
    public void add() {
        GsCode gsCode = codeService.add("pages/visitresults/main?venueId=8ab3b87674d2655e0174d274572d0009",
            1, "8ab3b87674d2655e0174d274572d0009");
        Assert.assertNotNull(gsCode);
    }

    @Test
    public void update() {
        Optional<GsCode>  optionalGsCode = codeService.findById("402882817511509201751150eaf00000");
        GsCode code = optionalGsCode.get();
        code.setCodeName("注册码更新");
        GsCode updateCode = codeService.update(code,code.getId());
        Assert.assertEquals(code.getCodeName(), updateCode.getCodeName());
    }

    @Test
    public void findById() {
        Optional<GsCode> optionalGsCode = codeService.findById("402882817511509201751150eaf00000");
        Assert.assertNotNull(optionalGsCode.get());
    }
    @Test
    public void list() {
        List<Map<String, Object>>  codeList = codeService.list(2);
        Assert.assertNotNull(codeList.get(0));
    }

    @Test
    public void pageList() {
        Page<Map<String, Object>> pageList = codeService.pageList(1, PageRequest.of(0, 10));
        Long items = pageList.getTotalElements();
        assertThat(items, allOf(greaterThan(0L), lessThan(11L) ) );
    }
    @Test
    public void delete() {
        codeService.delete("402882817511509201751150eaf00000");
        Optional<GsCode> optionalGsCode = codeService.findById("402882817511509201751150eaf00000");
        Assert.assertNull(optionalGsCode.get());
    }
    @Test
    public void findCodeListByIdList() {
        List<String> codeList = new ArrayList();
        codeList.add("8ab3b87674d2e0b70174d364a7610001");
        List<Map<String, Object>>  resultList = codeService.findCodeListByIdList(codeList);
        Assert.assertSame(1, resultList.size());
    }
}

上面就是最简单的单元测试写法,顶部只要@RunWith(SpringRunner.class))和 SpringBootTest即可,想要执行的时候,鼠标放在对应的方法,右键选择run该方法即可。 测试用例中我使用了assertThat断言,下文中会介绍,也推荐大家使用该断言。

Controller单元测试

上面只是针对Service层做测试,但是有时候需要对Controller层(API)做测试,这时候就得用到MockMvc了,可以不必启动工程就能测试这些接口。

MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。

Controller类:

 

 

 

package com.sncy.fuse.controller;
/**
 * @author HJW
 * @Description 二维码Controller
 */
@Slf4j
@RestController
@Api(tags = "二维码 接口")
@RequestMapping("gsCode")
public class GsCodeController {
    @Autowired
    IGsCodeService gsCodeService;

    @GetMapping("/list")
    @ApiOperation(value = "查询二维码信息列表,无分页", notes = "说明信息")
    @ApiImplicitParam(name = "cType", dataType = "int", paramType = "query", value = "二维码类型", required = true)
    public Result<List<Map<String, Object>>> list(@RequestParam int cType) {
        try {
            List<Map<String, Object>> codeInfoList = gsCodeService.list(cType);
            log.info("查询二维码信息列表,无分页,codeInfoList:" + codeInfoList);
            return new Result(ResultCode.CODE_OK.getValue(), ResultCode.CODE_OK.getDesc(), codeInfoList);
        } catch (Exception e) {
            log.error("查询二维码信息列表,无分页 异常!", e);
            return new Result(ResultCode.CODE_Error_BUSINESS.getValue(), "操作失败,请稍后重试!", null);
        }
    }

    @GetMapping("/pageList")
    @ApiOperation(value = "查询二维码信息列表,有分页", notes = "说明信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cType", dataType = "int", paramType = "query", value = "二维码类型", required = true),
            @ApiImplicitParam(name = "pageNumber", dataType = "int", paramType = "query", value = "当前页数,从0开始", required = true),
            @ApiImplicitParam(name = "pageSize", dataType = "int", paramType = "query", value = "每页条数", required = true)
    })
    public Result<Page<Map<String, Object>>> leaderPageList(int cType, Integer pageNumber, Integer pageSize) {
        try {
            Pageable pageable = PageRequest.of(pageNumber, pageSize);
            Page<Map<String, Object>> pageList = gsCodeService.pageList(cType, pageable);
            log.info("查询二维码信息列表,有分页,pageList:" + pageList);
            return new Result(ResultCode.CODE_OK.getValue(), ResultCode.CODE_OK.getDesc(), pageList);
        } catch (Exception e) {
            log.error("查询二维码信息列表,有分页 异常!", e);
            return new Result(ResultCode.CODE_Error_BUSINESS.getValue(), "操作失败,请稍后重试!", null);
        }
    }

    @GetMapping("/downloadCode/{id}")
    @ApiOperation(value = "下载二维码", notes = "说明信息")
    @ApiImplicitParam(name = "id", dataType = "string", paramType = "query", value = "二维码id", required = true)
    public Result downloadCode(HttpServletRequest request, HttpServletResponse response, @PathVariable String id) {
        log.error("下载二维码! {}", id);
        if (StringUtils.isBlank(id)) {
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值