2015-02-18 4 views
2

У меня есть класс, который я хочу протестировать с помощью mockito. Лучший способ описать класс - вставить код, но я постараюсь сделать все возможное в короткой фразе.Mock Asynchronous Call from void class

Класс имеет одну функцию void и вызывает другой объект, который передается через методы setter и getter. Объект, который вызывается (из функции void), является асинхронным вызовом.

Проблема, с которой я столкнулся, заключается в издевательском асинхронном вызове, который использует функция void (тестирование через junit).

pubic class Tester { 

    private Auth auth; // not mock'ed or spy'ed 
    @Mock private Http transport; 

    @Before 
    .... 

    @Test 
    public void testVoidFunctionFromAuth() { 

     doAnswer(new Answer<Object>() { 
      @Override 
      public Object answer(InvocationOnMock invocation) throws Throwable { 
       return doOutput(); 
      } 
     }).when(transport).executeAsync(param1, param2, param3...); 

     auth.obtainAuth(); // void function that uses transport mock class 
          // obtainAuth calls transport.executeAsync() 
          // as part of the code 

    } 

    // return type of transport.executeAsync() is 
    // ListenableFuture<ResponseEntity<String>> 
    private ListenableFuture<ResponseEntity<String>> doOutput() {  
     return new SimpleAsyncTaskExecutor() 
     .submitListenable(new Callable<ResponseEntity<String>>() { 
      @Override 
      public ResponseEntity<String> call() throws Exception { 
       .... 
       return responseEntity 
      } 
     }); 
    } 
} 

Что происходит, что функция doOutput() вызывается перед темauth.obtainAuth(); и когда obtainAuth() пытается вызвать doOutput() возвращает null - скорее всего потому, что doOutput уже выполнить на линии раньше. Я не уверен, как связать/вставить класс mock'ed (транспорт) по вызову executeAsync.

+0

Как правило, только макетный объект возвращает значение мгновенно, при необходимости завернутое в будущее. – chrylis

+0

@chrylis ya, который обычно работает, но мы хотим, чтобы объект mock'ed, '' 'Auth''' фактически не использовался (делает HTTP-запрос). Помимо объема тестирования. – Adam

+0

Вот почему вы используете макет; вы фактически не загружаете объект, который делает запросы. Похоже, вы не совсем поняли, что такое макет. – chrylis

ответ

0

Я не уверен, понял ли я этот вопрос, но как указано chrylis, объект mock мгновенно возвращает значение.

Единичный тест должен иметь свой собственный контекст и не зависит от внешних ресурсов, поэтому нет смысла тестировать сам асинхронный вызов. Он должен возвращать разные значения, чтобы вы могли тестировать поведение классов, которые его используют.

Для лучшего понимания макете определения взглянуть на это сообщение: What is Mocking?

Цитирование от Pro Spring MVC с Web Flow, испытания блока должны

Run быстро: единичный тест должен выполняться очень быстро. Если ему нужно подождать для базы данных соединений или внешних процессов сервера или для синтаксического анализа больших файлов, то его полезность будет быстро ограничена. Тест должен обеспечить немедленный отклик и мгновенное удовлетворение .

Имеет нулевую внешнюю конфигурацию:. В модульном тесте не должно быть никаких внешних файлов конфигурации , даже простых текстовых файлов. Конфигурации теста должны быть предоставлены и установлены самой тестовой картой по коду. Цель состоит в том, чтобы свести к минимуму как время выполнения теста , так и устранить внешние зависимости (которые могут меняться в течение времени, не синхронизироваться с тестом). Условия тестового случая должны быть выражены в тестовом каркасе, создавая более читаемый тест .

Эксплуатация независимо от других течений: Единичное испытание должно быть выполнено в полной изоляции. Другими словами, единичный тест не может зависеть от другого теста, который выполняется до или после него. Каждый тест представляет собой автономный блок . Фактически, каждый тестовый метод внутри теста должен быть автономным и не зависит от другого метода или от методов испытаний, выполняемых в определенном порядке .• Зависит от нулевых внешних ресурсов: единичный тест должен быть не зависит от каких-либо внешних ресурсов, таких как подключения к базе данных или веб-сервисов. Мало того, что эти ресурсы замедляют тестирование, но они находятся вне контроля теста и, следовательно, не гарантируют, что находятся в правильном состоянии для тестирования.

Оставьте внешнее состояние нетронутым: Единичное испытание не должно содержать никаких доказательств того, что он когда-либо работал. Единичные тесты записываются как повторяемые, поэтому они должны сами очистить. Очевидно, что это намного проще , когда тест не полагается на внешние ресурсы (которые часто сложнее очистить или восстановить).

Тест наименьшая единица кода возможных: Тест блок должен проверить наименьшую единицу кода возможного для того, чтобы выделить код под теста. В объектно-ориентированном программировании это устройство обычно представляет собой метод класса . Написание единичных тестов таким образом, что метод протестирован независимо от других методов уменьшает количество строк кода, что может содержать потенциальную ошибку.