首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单元测试框架spock和Mockito应用

单元测试框架spock和Mockito应用

作者头像
FunTester
发布2020-05-18 14:29:27
2.2K0
发布2020-05-18 14:29:27
举报
文章被收录于专栏:FunTesterFunTester

先介绍一下两位主角

spock是一款基于Groovy语言的单元测试框架,其基础也是JavaJunit,目前最新版已经到了2.0,但对Groovy和响应的Java版本要求较高,具体信息参考:Spock 2.0 M1版本初探

Mockito是一个模拟测试框架,可以让你用优雅,简洁的接口写出漂亮的单元测试。Mockito可以让单元测试易于可读,产生简洁的校验错误。TDD测试驱动开发要求我们先写单元测试,再写实现代码。在写单元测试的过程中,由于各种依赖的关系导致的阻碍,我们必需用到Mockito类似的框架来完成资源、对象的模拟。

Gradle配置

    testCompile 'org.mockito:mockito-core:2.7.22'
    testCompile group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5'
    testCompile group: 'org.springframework', name: 'spring-test', version: '5.1.9.RELEASE'
    testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0'
    testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.2'

Demo代码

下面是演示代码:

package com.FunTester.mockito.practise

import org.apache.http.client.methods.HttpRequestBase
import org.slf4j.Logger
import spock.lang.Shared
import spock.lang.Specification

import static com.fun.config.Constant.SPACE_1
import static com.fun.frame.SourceCode.getLogger
import static org.mockito.AdditionalAnswers.returnsFirstArg
import static org.mockito.Matchers.anyInt
import static org.mockito.Mockito.*

class Demo extends Specification {

    @Shared
    Logger logger = getLogger(this.getClass().getName())

    @Shared
    List listsss = mock(List)

    @Shared
    HttpRequestBase httpRequestBase = mock(HttpRequestBase.class)

    def setup() {
        logger.info("测试方法开始了")
    }

    def cleanup() {
        logger.info("测试方法结束了")
    }

    def setupSpec() {
        logger.info("测试类[${getClass().getName()}]开始了")
    }

    def cleanupSpec() {
        logger.info("测试类[${getClass().getName()}]结束了")
    }

    def "这是一个普通的demo"() {
        given:"创建一个存根list,添加一些元素"
        List mockedList = mock(List.class);
        mockedList.add("one");
        mockedList.add("two");
        mockedList.add("three times");
        mockedList.add("three times");
        mockedList.add("three times");
        when(mockedList.size()).thenReturn(5);
        mockedList.add("3")
        mockedList.add("3")
        mockedList.add("3")
        mockedList.add("3")

        expect:"验证属性以及方法调用次数"
        5 == mockedList.size()
        false == verify(mockedList, atLeastOnce()).add("one")
        false == verify(mockedList, times(3)).add("three times")
        false == verify(mockedList, atMost(4)).add("3")
        false == verify(mockedList, never()).add("30")
    }

    def "这是一个测试的mockito模拟方法返回"() {
        given: "虚拟一个迭代器对象"
        def iterator = mock(Iterator.class)
        when(iterator.next()).thenReturn("hello").thenReturn("world")

        expect: "测试迭代器元素拼接"
        "hello world" == iterator.next() + SPACE_1 + iterator.next()
    }

    def "这是一个测试,用来在对象初始化之后mock对象的"() {
        given: "创建对象后再Mockito"
        def iterator = new ArrayList()
        iterator.add("323")
        def list = spy(iterator)
        doReturn("fun").when(list).get(3)
        doReturn(3).when(list).get(0)

        expect:
        list.contains("323")
        "fun" == list.get(3)
        3 == list.get(0)
    }

    def "这是一个测试,抛出异常的测试用例"() {
        given: "创建测试对象"
        def object = mock(ArrayList.class)
        when(object.get(1)).thenThrow(new IndexOutOfBoundsException("我是测试"))//只能抛出可能的抛出的异常
        def re = 0
        try {
            object.get(1)
        } catch (IndexOutOfBoundsException e) {
            re = 1
        }

        expect:
        re == 1
    }

    def "这是一个测试方法返回值的用例"() {
        given:
        def j = mock(DemoJ.class)
        doAnswer(returnsFirstArg()).when(j).ds(anyInt(), anyInt())

//        when(list.add(anyString())).thenAnswer(returnsFirstArg());
        // with then() alias:
//        when(list.add(anyString())).then(returnsFirstArg());
        expect:
        3 == j.ds(3, 32)

    }

    def "我是测试共享Mock对象的用例"() {
        given:

        when(listsss.get(anyInt())).thenReturn(3)

        expect:
        3 == listsss.get(3)
    }

/**
 *      对于未指定mock的方法,spy默认会调用真实的方法,有返回值的返回真实的返回值,而mock默认不执行,有返回值的,默认返回null
 */
    def "spy和mock区别"() {
        given:
        def list = [1,2,3,4]
        def integers = spy(list)
        when(integers.size()).thenReturn(9)

        expect:
        integers.size() == 9
        integers.get(0) == 1

    }
}

  • 经过我的测试,Mockito的基础功能在spock应用还是非常流畅的,但是一些高级语法还是无法使用,如果在实际项目中使用请多调研两者差别,大概率还是要混合编程。

参考文章:


  • 郑重声明:“FunTester”首发,欢迎关注交流,禁止第三方转载。更多原创文章:FunTester十八张原创专辑,合作请联系Fhaohaizi@163.com
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FunTester 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 先介绍一下两位主角
  • Gradle配置
  • Demo代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档