2016-03-29 8 views
2

Я очень новичок в споке, и я не нашел никакого примера, что мне нужно, поэтому я считаю, что лучший способ - показать пример того, что мне нужно.Спок - насмешливое внешнее обслуживание

  1. e.g. тестовый класс в Spock:

    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 класс, и вы не можете изменить это, вы можете использовать частичный Mock в Спока. Этот тип испытаний трудно поддерживать и может иметь большой побочный эффект:

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" 
} 
Смежные вопросы