2016-03-29 132 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" 
}