Spock集成入门

本文基于SpringBoot

在pom.xml添加Spock依赖

        <!-- test -->
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.4.12</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
        <groupId>org.spockframework</groupId>
        <artifactId>spock-core</artifactId>
        <version>1.1-groovy-2.4</version>
        <scope>test</scope>
        </dependency>

 

新建Sum.java

1 public class Sum {
2     public int sum(int a, int b) {
3         return a + b;
4     }
5 }

 

新建groovy测试脚本SpockSpecification.groovy

  1 package com.test.bookup
  2 
  3 import com.example.demo.Sum
  4 import spock.lang.Specification
  5 import spock.lang.Unroll;
  6 
  7 /**
  8  * Created by hande on 2018/7/18.
  9  */
 10 class SpockSpecification extends  Specification{
 11 
 12     // 调用外部类测试
 13     def sum = new Sum();
 14     def "get sum"(){
 15         expect:
 16         sum.sum(1,1) == 2
 17     }
 18 
 19     // Where Blocks 简单大小比较函数测试
 20     def "get max num"(){
 21         expect:
 22           Math.max(a,b) == c
 23 
 24         where:
 25           a|b|c
 26           1|2|2
 27           1|2|2
 28           2|3|3
 29     }
 30 
 31     def "get min num"(){
 32         expect:
 33         Math.min(a,b) == c
 34 
 35         where:
 36         a|b|c
 37         1|2|1
 38         1|2|1
 39         2|3|2
 40     }
 41 
 42     // 上述例子实际会跑三次测试,相当于在for循环中执行三次测试,如果在方法前声明@Unroll,则会当成三个方法运行。
 43     @Unroll
 44     def "@Unroll test"(){
 45         expect:
 46         Math.min(a,b) == c
 47 
 48         where:
 49         a|b|c
 50         1|2|1
 51         1|2|1
 52         2|3|2
 53     }
 54 
 55     // where block另外两种数据定义方法
 56     def "where block data init method"(){
 57         expect:
 58             Math.max(a,b) == c
 59 
 60         where:
 61             a|_
 62             3|_
 63             7|_
 64             0|_
 65 
 66             b<<[5,0,0]
 67 
 68             c=a>b?a:b
 69     }
 70 
 71 
 72 
 73     // When and Then Blocks
 74     def "When and Then Blocks"(){
 75         setup:
 76           def stack = new Stack();
 77           def em = "push me";
 78 
 79         when:
 80           stack.push(em);
 81 
 82         then:
 83           !stack.empty();
 84           stack.size() == 1;
 85           stack.peek() == em;
 86     }
 87 
 88 
 89 
 90     // mock应用
 91     Publisher publisher = new Publisher()
 92     Subscriber subscriber = Mock()
 93     Subscriber subscriber2 = Mock()
 94 
 95     def setup() {
 96         publisher.subscribers.add(subscriber)
 97         publisher.subscribers.add(subscriber2)
 98     }
 99 
100     def"should send messages to all subscribers"(){
101         when:
102         publisher.send("hello")
103 
104         then:
105         1*subscriber.receive("hello")
106         1*subscriber2.receive("hello")
107     }
108     // 上面的例子里验证了:在publisher调用send时,两个subscriber都应该被调用一次receive(“hello”)。
109 }

 

表达式中的次数、对象、函数和参数部分说明

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

 

Stubbing

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

subscriber.receive(_)>>"ok"

 

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

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

 

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

subscriber.receive(_)>>{thrownewInternalError("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,不限制次数。

 

posted @ 2018-07-18 10:24  UniqueColor  阅读(1450)  评论(0编辑  收藏  举报