2016-03-29 135 views
2

我是spock的新手,我沒有找到任何我需要的示例,所以我認爲最好的方法是展示我需要的示例。Spock - 嘲笑外部服務

  1. 例如,測試類中斯波克:

    def "getData"(){ // this is test of getData method from ExternalService 
        when: 
        Result result = externalService.getData() 
        then: 
        result.msg = 'SUCCESS' 
    } 
    
  2. 類:

    public class ExternalService(){ 
        private ServiceConnector serviceConnector; 
    
        public Result getData(){ 
        Result result = serviceConnector.callAndGet(); 
        prepareInformation(data); 
        updateStatuses(data); 
        return result; 
        } 
    } 
    
  3. 類的數據:

    public class Data{ 
        private String msg; 
        private int Id; 
        // +getters/setters 
    } 
    

現在我的getData測試,並想嘲笑唯一方法callAndGet() 。這意味着每次我撥打callAndGet時,我需要有msg的對象數據SUCCESS,但是應該正常調用getData方法的所有其他方法。

這可以理解嗎?你可以幫幫我嗎?

回答

7

你需要做的是嘲笑ServiceConnector類並通過構造函數(如)傳遞它。見下:

@Grab('org.spockframework:spock-core:1.0-groovy-2.4') 
@Grab('cglib:cglib-nodep:3.1') 


import spock.lang.* 

class Test extends Specification { 
    def 'some spec'() { 
     given:  
      def serviceConnector = Mock(ServiceConnector) { 
       callAndGet() >> new Result(msg: 'SUCCESS') 
      } 
      def externalService = new ExternalService(serviceConnector) 

     when: 
      Result result = externalService.getData() 

     then: 
      result.msg == 'SUCCESS' 
    } 
} 

public class ExternalService { 
    private ServiceConnector serviceConnector 

    public ExternalService(ServiceConnector serviceConnector) { 
     this.serviceConnector = serviceConnector 
    } 

    public Result getData() { 
    Result result = serviceConnector.callAndGet() 

    prepareInformation(result) 
    updateStatuses(result) 
    result 
    } 

    private void prepareInformation(Result data) { 
    } 

    private void updateStatuses(Result data) { 
    } 
} 

public class ServiceConnector { 
    public Result callAndGet() { 

    }  
} 

public class Result { 
    String msg 
} 
2

你不應該試圖嘲笑你的服務「只有一種方法」。這只是一個糟糕的設計的標誌,你的代碼是不可測試的。你應該更好地用小型服務來隔離你的類的依賴關係,並在單元測試中嘲笑這些服務。然後用集成測試和完整的依賴關係實現測試上層。

在你的例子中,ServiceConnector應該是一個接口,可以很容易地模擬。有了這個條件,通過測試可以寫爲:

def "test a mocked service connector"() { 
    given: "a service connector" 
    def serviceConnector = Mock(ServiceConnector) 

and: "an external service" 
    def externalService = new ExternalService(serviceConnector:serviceConnector) 

when: "Data is loaded" 
    def result = externalService.data 

then: "ServiceConnector is called" 
    serviceConnector.callAndGet() >> new Result(msg:"SUCCESS") 

and: "Data is mocked" 
    result.msg == "SUCCESS" 
} 

但是,如果ServiceConnector是一個類,你不能改變這一點,你可以使用一個斯波克部分模擬。這種測試很難維護,並且會產生很多副作用:

def "test a mocked service connector"() { 
    given: "a service connector" 
    def serviceConnector = Spy(ServiceConnector) { 
     callAndGet() >> new Result(msg:"SUCCESS") 
    } 

and: "an external service" 
    def externalService = new ExternalService(serviceConnector:serviceConnector) 

when: "Data is loaded" 
    def result = externalService.data 

then: "Data is mocked" 
    result.msg == "SUCCESS" 
}