首页 > 其他分享 >关于单测技术选型,聊聊我的思考

关于单测技术选型,聊聊我的思考

时间:2023-04-11 21:35:41浏览次数:53  
标签:given 单测 框架 代码 Mockito 选型 Spock 聊聊

对于单测来说,目前常用的单测框架有:

  • JUnit
  • Mockito
  • Spock
  • PowerMock
  • JMockit
  • TestableMock

其中 JUnit 不支持 Mock,因此基本不会只用 JUnit,而是结合其他有 Mock 功能的框架一起使用。从知名度及使用率来说,Mockito 和 Spock 使用较多,而 PowerMock、JMockit、TestableMock 使用较少。下面我们将主要对比 Mockito 和 Spock 两种框架的差异。

Mockito

Mockito 是 Java 单元测试中的 Mock 框架,一般都是与 JUnit 一起使用。Mockito 功能强大,几乎所有你能想到的功能都支持,并且由于发布时间较长,因此使用的人非常多。

  • 优点:功能强大、使用人数多、资料丰富。
  • 缺点:代码不够简洁、没有统一的单测结构、不支持静态方法和私有方法 Mock。

更多信息详见官网:https://site.mockito.org/

Spock

Spock 是一个企业级的测试规范框架,可用来测试 Java 和 Groovy 应用。Spock 最大的特色是其简洁美观的语言规范。Spock 兼容绝大多数 IDE、编译工具和 CI 集成服务器。Spock 框架使用 Groovy 语言编写,而 Groovy 语言则是 Java 语言的超集,绝大多数 Java 语言语法在 Groovy 中都支持。

  • 优点:单测结构统一、代码简洁、异常测试及参数测试支持更好。
  • 缺点:学习成本略高、不支持静态方法和私有方法 Mock。

更多信息详见官网:https://spockframework.org/

Mockito vs Spock

Spock vs JUnit 5 - the ultimate feature comparison 中详细对比了 Mokito 与 Spock 的差异,他们在发展情况、学习曲线、工具支持等方面的比较如下图所示。

从上图可以看到,Mockito 框架在发展、学习曲线、工具支持、从 JUnit4 迁移几方面比较有优势。而 Spock 框架则在测试结构、异常测试、条件测试等方面比较有优势。因此,选择哪个测试框架完全基于实际情况。例如,如果你目前的情况是:

  1. Java 是唯一的语言。
  2. 想要更强的编译时错误检查。
  3. 更稳定、更主流的实现方式。

那么选择 JUnit + Mockito 的方式是更好的选择。但如果你目前的情况是:

  1. 希望单测跟简单易读
  2. 更简洁的参数测试与异常测试

那么选择 Spock 会是更好的选择。

为啥选择 Spock?

根据前面的分析,Mockito 的主要优势在于比较稳定、主流,缺点在于不够简洁易读。而 Spock 虽然使用人群没有 Mockito 那么多,但国内也有一些大厂在使用 Spock,例如美团等(可参考:Spock单元测试框架介绍以及在美团优选的实践)。

我们重视写单测,但是又不希望写单测花费太多时间,毕竟业务才是第一位的。因此,我们希望单测代码尽可能简洁、可维护。 基于这个原因,我们选择了 Spock 框架作为朝昔后端的单测框架解决方案。而 Spock 不支持 static 方法及 private 方法 Mock 的缺陷,则尝试通过整合 PowerMock 或 TestableMock 来解决。

可维护性更强

在极客时间《程序员的测试课》中,有一节关于讲了一个好的自动化测试长什么样?在这里面,作者提到一个好的单测应该由 准备、执行、断言、清理 4 个阶段组成。

对于 Mockito 而言,它并没有规定具体的代码规范,因此只能依靠注释来标注哪些代码是准备阶段的代码,哪些是执行阶段的代码,哪些是断言阶段的代码,如下代码所示。

class SimpleCalculatorTest {
    @Test
    void shouldAddTwoNumbers() {
        //given 准备
        Calculator calculator = new Calculator();
        //when 执行
        int result = calculator.add(1, 2);
        //then 断言
        assertEquals(3, result);
    }
}

对于 Spock 而言,其通过 given-when-then 的结构,强制要求编写者将不同阶段的代码放到不同的位置,从而增强了可读性。同样是用于测试计算器的加法函数的单测用例,使用 Spock 框架编写的单测如下代码所示。

class SimpleCalculatorSpec extends Specification {
    def "should add two numbers"() {
        given: "create a calculater instance"
            Calculator calculator = new Calculator()
        when: "get calculating result via the calculater"
            int result = calculator.add(1, 2)
        then: "assert the result is right"
            result == 3
    }
}

可以看到,通过 given-when-then 结构的划分,我们可以更加快速地弄清楚单测的内容,从而提高单测的可读性,使得单测更加容易维护。

代码更加简洁

对于 Mockito 与 Spock 而言,它们之间的一个很大的差别是:Spock 的代码更加简洁。这个特性可以让我们编写比 Mockito 更少的代码,从而实现同样的功能。例如在 Mockito 中,我们 Mock 某个接口实现时,通常需要写一长串的 give(...).return(...) 代码。而在进行断言的时候,也需要写比较长的 then(xx).should(xx).checkxx() 代码,如下图所示。

@Test
public void should_not_call_remote_service_if_found_in_cache() {
    //given
    given(cacheMock.getCachedOperator(CACHED_MOBILE_NUMBER)).willReturn(Optional.of(PLUS));
    //when
    service.checkOperator(CACHED_MOBILE_NUMBER);
    //then
    then(webserviceMock).should(never()).checkOperator(CACHED_MOBILE_NUMBER);
    verify(webserviceMock, never()).checkOperator(CACHED_MOBILE_NUMBER);  
}

但在 Spock 中的代码就相对比较简洁,如下所示代码实现了上述 Mockito 代码同样的功能。

def "should not hit remote service if found in cache"() {
    given:
        cacheMock.getCachedOperator(CACHED_MOBILE_NUMBER) >> Optional.of(PLUS)
    when:
        service.checkOperator(CACHED_MOBILE_NUMBER)
    then:
        0 * webserviceMock.checkOperator(CACHED_MOBILE_NUMBER)
}

可以看到,Spock 没有 given、willReturn 等关键词,而是取而用 >> 等符号来实现,这样代码更加简洁,阅读起来也更加明了。

案例代码对比:https://www.yuque.com/lugew/spock/wkxhvk

标签:given,单测,框架,代码,Mockito,选型,Spock,聊聊
From: https://www.cnblogs.com/chanshuyi/p/talk-about-unit-test-tech-selection.html

相关文章

  • 聊聊如何运用JAVA注解处理器(APT)
    什么是APTAPT(AnnotationProcessingTool)它是Java编译期注解处理器,它可以让开发人员在编译期对注解进行处理,通过APT可以获取到注解和被注解对象的相关信息,并根据这些信息在编译期按我们的需求生成java代码模板或者配置文件(比如SPI文件或者spring.fatories)等。APT获取注解及生成代......
  • 国产即时通讯软件如何选型?
    多年来,国内计算机底层标准、架构、生态等大多由国外IT巨头制定,一直以来来自国际的威胁国内信息安全的事件不断发生。基于这些问题,国内逐渐建立起基于自己的计算机底层架构和标准,形成自主可控的开放生态,但不少单位在采用国产计算机后,原先所使用的即时通讯软件没有做兼容支持,无法继......
  • 国产即时通讯软件如何选型?
    多年来,国内计算机底层标准、架构、生态等大多由国外IT巨头制定,一直以来来自国际的威胁国内信息安全的事件不断发生。基于这些问题,国内逐渐建立起基于自己的计算机底层架构和标准,形成自主可控的开放生态,但不少单位在采用国产计算机后,原先所使用的即时通讯软件没有做兼容支持,无法继续......
  • 用 JaCoCo 生成单测覆盖率报告
    我们都知道Spock是一个单测框架,其特点是语法简明。但当我们使用Spock写了一堆单元测试之后,如何生成对应的单测覆盖率报告呢?一般来说,我们会使用两个插件来一起完成单测覆盖率报告的生成,分别是:MavenSurefirePluginJaCoCoPlugin其中MavenSurefirePlugin是用来在Mave......
  • 超详细!手把手教你用 JaCoCo 生成单测覆盖率报告!
    我们都知道Spock是一个单测框架,其特点是语法简明。但当我们使用Spock写了一堆单元测试之后,如何生成对应的单测覆盖率报告呢?一般来说,我们会使用两个插件来一起完成单测覆盖率报告的生成,分别是:MavenSurefirePluginJaCoCoPlugin其中MavenSurefirePlugin是用来在Mave......
  • Go 语言体系下的微服务框架选型: Dubbo-go
    本文介绍了Go微服务体系发展与选型,过去一年优雅上下线以及对未来的展望。作者简介:牛学蔚(GitHub:@justxuewei):ApacheDubboPMC,对云原生、中间件、容器等领域有浓厚兴趣,活跃在Dubbo和Katacontainers两个开源项目中。一、Go微服务体系发展与选型随着微服务技术的快速发展,其在......
  • o型圈沟槽尺寸标准以及选型规格表
    因为O型圈是性价比比较高的密封件,所以O型圈在液压元件和气动元件中具有广泛的用途,今天,我们就来说一下O型圈沟槽尺寸标准以及选型规格表。 如果能提供适当的工具条件和设备,O型圈既可用作静态密封也能用于动态密封,相较于其他的密封件,O型圈所需要空间更少,使得设计以及安装更容易,要想......
  • 聊聊spring中bean的作用域
    前言今天分享一下springbean的作用域,理解bean的作用域能够在使用过程中避免一些问题,bean的作用域也是springbean创建过程中一个重要的点。Springbean的作用域类型singleton(单例模式):在整个应用程序的生命周期中,只创建一个Bean实例。默认情况下,所有的Bean都是单例模式。p......
  • pytest生成简单测试报告命令,不用安装插件
    --junit-xml=./repot/result.xml生成JunitXML文件可在命令终端输入:pytest./case/test_DS_004.py--junit-xml=./repot/result.xml    --pastebin=all生成在线测试报告可在命令终端输入:pytest./case/test_DS_004.py--pastebin=all ......
  • 聊聊spring中bean的作用域
    前言今天分享一下springbean的作用域,理解bean的作用域能够在使用过程中避免一些问题,bean的作用域也是springbean创建过程中一个重要的点。Springbean的作用域类型singleton(单例模式):在整个应用程序的生命周期中,只创建一个Bean实例。默认情况下,所有的Bean都是单例模式。p......