Search code examples
groovymockingspockgrails-servicesgrails-test

Spock - mocking external service


I'm very new in spock framework testing and I didn't find any example where I can find needed information. Therefore, I think the best way is to show an example what I need to have.

  1. e.g. test class in spock:

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

    public class ExternalService(){
      private ServiceConnector serviceConnector;
    
      public Result getData(){
        Result result = serviceConnector.callAndGet(); 
        prepareInformation(data);
        updateStatuses(data);
        return result;
      }
    }
    
  3. Class Data as a Domain Class:

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

And now I have getData test and would like to mock the only method callAndGet(). It means every time I call callAndGet I need to have object Data with msg SUCCESS but all other methods from getData method should be called normally.

Is it quite understandable? The question is how can we inject/mock the service class ExternalService into the spock test class?


Solution

  • What you need to do is to mock the ServiceConnector class and pass it via constructor (e.g.). See below:

    @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
    }