• spock框架进行单元测试的学习与实践


    单元测试

    一个稳定的系统少不了单元测试,单元测试(又称为模块测试, Unit Testing)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。
    对于面向对象编程,最小单元就是方法,包括父类、抽象类、或者子类中的方法。
    所以单元测试的特点:

    • 测试的是一个代码单元内部的逻辑,而不是各模块之间的交互。
    • 无依赖,不需要实际运行环境就可以测试代码。
    • 运行效率高,可以随时执行。

    而单元测试的应用场景一般主要有这几个:

    • 测试驱动开发,由于工期限制,几乎无法实现
    • 对每次代码修改做回归测试

    spock测试框架

    简介

    Spock是基于JUnit的单测框架,提供一些更好的语法,结合Groovy语言,可以写出更为简洁的单测,它的语法完全遵循 BDD(行为驱动开发) 风格的结构。同时集成了像 Jmock、Mockito 等语法表达风格于一体,使得它很简洁有很高的可读性

    与其他单元测试框架对比

    Spock相比JUnit有易读、简洁、自带Mock等特性,可以减少单元测试编写时间,而且bug更少,可读性更好,写出的单元测试代码更优雅,更易于阅读!
    Spock提供了覆盖Java企业应用的完整的测试生命周期。其他框架,是基于某种需要产生的,比如:Junit单纯用于单测,但不提供mock;Mockito提供mock功能,但不提供静态类的mock;PowerMock提供静态类mock;
    它们之间需要整合,且不容易跟上新的测试场景。Spock提供了全家桶测试,内置了mock和stub功能等,很方便上手

    特点

    • 全能,高效,代码简介,易读,方法名支持中文
    • 提供Groovy的closures,类似Java8的lambda表达式
    • Mockito对参数匹配有限制。如果在方法中使用匹配器,那么所有的参数都需要匹配器。Spock不受此限制,可以将实参与实参匹配器混合和匹配
    • Spock区分了Stub和Mock,让单测更易读
    • Spock提供了更多详细的错误信息

    基础

    关于依赖

    依赖如果版本对不上会报各种各样的错,所以最好是根据maven仓库中查看版本,一定要对应上:
    比如如果是3.0版本的spock-core,groovy依赖就必须是:

    基本用法

    需要创建groovy类使用spock,所有的类都要继承Specification类,如下:

    class SpockDemoSpec extends Specification{
        /**
         * 在第一个测试方法开始前执行一遍
         */
        def setupSpec() { println "------------ setupSpec: 所有测试开始之前执行 ------------" }
    
        /**
         * 每个测试方法开始前都会执行一遍
         */
        def setup() { println "------------ setup:每个测试方法开始之前执行 ------------" }
    
        /**
         * 每个测试方法后都会执行一遍
         */
        def cleanup() { println "------------ cleanup:每个测试方法结束之后执行 ------------" }
    
        /**
         * 最后一个测试方法后执行
         */
        def cleanupSpec() { println "------------ cleanupSpec: 所有测试方法结束之后执行 ------------" }
    
        def "测试given-expect"() {
            given:
            def a = new Random().nextInt(10)
            def b = 2
            expect:
            println a
            a > b
        }
    
        def "测试where"() {
            expect:
            result == ++id
            // where表格 左边是参数,右边是测试结果
            where:
            id | result
            10  | 11
            100  | 101
            1000  | 1001
        }
    
        def "测试given-when-then"() {
            given:
            // 数据准备
            def a = "houzheng"
            when:
            // 条件判断
            boolean flag = a.equals("houzheng")
            then:
            // 期望结果
            flag
        }
    
        def "测试异常thrown"() {
            when:
            // 此方法会抛出RuntimeException
            throw new RuntimeException("模拟异常");
            then:
            // 接收异常
            def ex = thrown(Exception)
            ex.class.name == "java.lang.RuntimeException"
            ex.getMessage() == "模拟异常"
        }
    }
    

    Demo执行结果:

    • where: 以表格的形式提供测试数据集合
    • when: 触发行为,比如调用指定方法或函数
    • then: 做出断言表达式
    • expect: 期望的行为,when-then的精简版
    • given: mock单测中指定mock数据
    • thrown: 如果在when方法中抛出了异常,则在这个子句中会捕获到异常并返回
    • def setup() {} :每个测试运行前的启动方法
    • def cleanup() {} : 每个测试运行后的清理方法
    • def setupSpec() {} : 第一个测试运行前的启动方法
    • def cleanupSpec() {} : 最后一个测试运行后的清理方法

    springboot中的使用

    常用注解

    项目中实际使用

    笔者目前项目中某个业务的使用

    与原来单元测试代码的对比

    打包运行

    测试报告输出

    心得体会与总结

    • 兼容性比较差,依赖版本稍微不对,就会报一些莫名其妙的错误,而且提示也不明显,不太好排查
    • 其实虽然说要懂groovy,但是懂java的人还是非常容易上手的,只要给一个demo,基本就能够写单测了
    • 如果还想写的更优雅更高级,那可以去学学groovy,这里放一下笔者的链接:https://www.cnblogs.com/houzheng/p/15183586.html , 有兴趣可以看看
  • 相关阅读:
    x264参数
    用X264编码以后的H264数据
    (转)YUV420存储格式
    YUV数据YUY2到I420
    udp编程中,一次能发送多少个bytes为好?
    (转)c++多态实现的机制
    linux下ping加时间戳实时输出到文件 放后台运行
    如何向AcmeAir注入问题代码
    AcmeAir
    Jmeter压力测试
  • 原文地址:https://www.cnblogs.com/houzheng/p/15781208.html
Copyright © 2020-2023  润新知