2016-03-29 12 views
2

私は非常にスポックで新しく、必要なものは何も見つけられませんでしたので、私が持っている必要がある例を示すことが最善の方法だと思います。Spock - mocking外部サービス

  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 成功でオブジェクトデータを持つ必要がありますが、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

サービスの「1つだけの方法」を模倣しようとするべきではありません。それはちょうど悪いデザインの兆候です、あなたのコードはテスト可能ではありません。小規模なサービスとクラスの依存関係を分離し、単体テストでこのサービスを模擬する方がよいでしょう。次に、統合テストと依存関係の完全実装で上位層をテストします。

あなたの例では、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" 
} 
関連する問題