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,不限制次數。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM