专栏首页搜狗测试Spock测试框架实践(六)

Spock测试框架实践(六)

在上一次Spock实践中我们介绍了Spock的文档化测试和HTTP接口测试实践,今天我们用Spock做一些mock的实践。

对于测试来说,除了能够对输入-输出进行验证之外,还希望能验证模块与其他模块之间的交互是否正确,比如“是否正确调用了某个对象中的函数”;或者期望被调用的模块有某个返回值,等等。各类mock框架让这类验证变得可行,而spock除了支持这类验证,并且做的更加优雅,下面我们看一下在Spock里mock的应用实践。

一、mock

首先我们在Spock中创建一个mock对象:

class PublisherSpec extends Specification {
     Publisher publisher = new Publisher()
     Subscriber subscriber = Mock()
     Subscriber subscriber2 = Mock()
     def setup() {
         publisher.subscribers.add(subscriber)
         publisher.subscribers.add(subscriber2)
     }
}

而创建了mock对象之后就可以对它的交互做验证了:

def "should send messages to all subscribers" () {
     when:
     publisher.send( "hello" )

     then:
     1 * subscriber.receive( "hello" )
     1 * subscriber2.receive( "hello" )
}

上面的例子里验证了:在publisher调用send时,两个subscriber都应该被调用一次receive(“hello”)。示例中,表达式中的次数、对象、函数和参数部分都可以灵活定义:

1 * subscriber.receive( "hello" )      // exactly one call
0 * subscriber.receive( "hello" )      // zero calls
( 1 .. 3 ) * subscriber.receive( "hello" ) // between one and three calls (inclusive)
( 1 .._) * subscriber.receive( "hello" ) // at least one call
(_.. 3 ) * subscriber.receive( "hello" ) // at most three calls
_ * subscriber.receive( "hello" )      // any number of calls, including zero
1 * subscriber.receive( "hello" )     // an argument that is equal to the String "hello"
1 * subscriber.receive(! "hello" )    // an argument that is unequal to the String "hello"
1 * subscriber.receive()            // the empty argument list (would never match in our example)
1 * subscriber.receive(_)           // any single argument (including null)
1 * subscriber.receive(*_)          // any argument list (including the empty argument list)
1 * subscriber.receive(! null )       // any non-null argument
1 * subscriber.receive(_ as String) // any non-null argument that is-a String
1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies the given predicate
                                           // (here: message length is greater than 3)
1 * subscriber._(*_)     // any method on subscriber, with any argument list
1 * subscriber._         // shortcut for and preferred over the above
1 * _._                  // any method call on any mock object
1 * _                    // shortcut for and preferred over the above

得益于groovy脚本语言的特性,在定义交互的时候不需要对每个参数指定类型,如果用过java下的其它mock框架应该会被这个特性深深的吸引住。

二、Stubbing

对mock对象定义函数的返回值可以用如下方法:

subscriber.receive(_) >> "ok"

符号代表函数的返回值,执行上面的代码后,再调用subscriber.receice方法将返回ok。如果要每次调用返回不同结果,可以使用:

subscriber.receive(_) >>> [ "ok" , "error" , "error" , "ok" ]

如果要做额外的操作,如抛出异常,可以使用:

subscriber.receive(_) >> { throw new InternalError( "ouch" ) }

而如果要每次调用都有不同的结果,可以把多次的返回连接起来:

subscriber.receive(_) >>> [ "ok" , "fail" , "ok" ] >> { throw new InternalError() } >> "ok"

三、mock and stubbing

如果既要判断某个mock对象的交互,又希望它返回值的话,可以结合mock和stub,可以这样:

then:
1 * subscriber.receive( "message1" ) >> "ok"
1 * subscriber.receive( "message2" ) >> "fail"

注意,spock不支持两次分别设定调用和返回值,如果把上例写成这样是错的:

setup:
subscriber.receive( "message1" ) >> "ok"
when:
publisher.send( "message1" )
then:
1 * subscriber.receive( "message1" )

此时spock会对subscriber执行两次设定:

  • 第一次设定receive(“message1″)只能调用一次,返回值为默认值(null)。
  • 第二次设定receive(“message1″)会返回ok,不限制次数。

四、其它类型的mock对象

Spock也支持spy、stub之类的mock对象,但是并不推荐使用,因为使用“正规的”BDD思路写出的代码不需要用这些方法来测试,官方的解释是:

Think twice before using this feature. It might be better to change the design of the code under specification.

(在使用此功能之前请三思。在规范下更改代码的设计可能会更好。)

具体的使用方法如果有兴趣可以参考官方文档.

本文分享自微信公众号 - 搜狗测试(SogouQA),作者:Eason

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-03-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spock测试框架实践

    测试同学们平时用的比较多的测试框架和工具,如JMockit、EasyMock、Mockito和PowerMock,大家普遍认为代码可读性差,多组测试数据使用起来...

    用户5521279
  • Spock测试框架实践(五)

    在上一次Spock实践中我们介绍了Spock的数据驱动和一些技巧,今天我们用Spock做一些测试实践。

    用户5521279
  • Spock测试框架实践(四)

    在上一次Spock实践中我们介绍了Spock的数据驱动和一些技巧,今天我们继续介Spock的一些实用技巧。

    用户5521279
  • Spock测试框架实践(二)

    在上一次Spock实践中我们介绍了Spock的优点和Demo的搭建,今天我们继续介绍一些Spock常用的实践。

    用户5521279
  • Spock测试框架实践(三)

    在上一次Spock实践中我们介绍了Spock的基本概念,今天我们继续介Spock的数据驱动和一些技巧。

    用户5521279
  • FunTester原创文章(基础篇)

    FunTester
  • 在Spring Boot项目中使用Spock框架

    Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring Boot项目中使用该框架写优雅、高效以及DSL...

    阿杜
  • JsonPath工具类封装

    在经历过一些波折之后,总算是把JsonPath工具类的封装类写好了,时间仓促。没有太严格的测试,等有机会我再用Groovy进行单元测试框架spock写一些单测来...

    FunTester
  • Spock 测试框架的介绍和使用详解

    Spock 框架是一个基于groovy语法的测试框架,由于使用groovy,所以使用起来比 junit 更加灵活,测试用例的写法更加简单易懂,一目了然。

    yawn

扫码关注云+社区

领取腾讯云代金券