Как выполнить модульное тестирование Spring RestTemplate, который принимает ResponseExtractor и RequestCallback? - PullRequest
0 голосов
/ 16 апреля 2020

Я занимаюсь разработкой в ​​Groovy и пытаюсь написать модульный тест Спока для следующего использования Spring RestTemplate ...

Включены мои функции обратного вызова и извлечения ответа и мой класс инициализации бин RestTemplate. Я использую ResponseExtractor для потоковой передачи ответа от GET myurl/ и скопировать его в файл. RequestCallback просто устанавливает некоторые заголовки для запроса.

class RestTemplateConfig() {
  @Bean(name = 'myRestTemplate')
  RestTemplate getMyRestTemplate() {
    RestTemplate restTemplate = new RestTemplateBuilder().build()
    return restTemplate
  }
}

class MyClass() {

  @Autowired
  @Qualifier('myRestTemplate')
  RestTemplate restTemplate

  File getFile() {

     ResponseExtractor<Void> responseExtractor = { ClientHttpResponse response ->
       // do something with the response
       // in this case, the response is an input stream so we copy the input stream to a file
       myFile = response.getBody() // roughly, in a psuedocode-ish way
       return null
     }

     RequestCallback requestCallback = { ClientHttpRequest request ->
       request.getHeaders().setAccept([MediaType.APPLICATION_JSON])
     }

     File myFile
     // get my file data
     restTemplate.execute('myurl/', HttpMethod.GET, requestCallback, responseExtractor)
     return myFile
  }
}

Документы Spring Framework для этого конкретного execute(...) метода: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#execute - java. net .URI-org. springframework.http.HttpMethod-org.springframework.web.client.RequestCallback-org.springframework.web.client.ResponseExtractor-

Как мне высказать, что происходит в этих замыканиях? В частности, я заинтересован в макете моего экстрактора ответов, потому что мой текущий тест всегда возвращает myFile как ноль.

    when:
    // do stuff

    then:
    1 * restTemplate.execute('myurl/, HttpMethod.GET, _, _) // how can I mock out the expected response here?
    0 * _

    myFile != null // this fails because myFile is null

1 Ответ

1 голос
/ 17 апреля 2020

После того, как вы обновили пример кода, как я и просил, теперь я могу видеть более четко. Вы страдаете от типичной (не) проблемы с тестируемостью: ваш метод getFile делает больше, чем просто получает файл. Он создает две зависимости как локальные переменные, делая их немоделируемыми, и, следовательно, весь метод в основном непроверяем.

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

  • Если requestCallback и responseExtractor могут быть введены через конструктор или установщик, вы можете ввести mock.
  • Если они созданы каким-то классом фабрики , вы можете заблокировать этот класс.
  • В случае использования фабричного метода внутри самого тестируемого класса вы можете использовать шпион для класса и заглушить фабричный метод.

Для более общего обсуждения тестируемости и того, как тесты определяют дизайн приложения, см. Мой другой ответ здесь , разделы «Общие комментарии» и «Обновление».

Если что-либо из этого неясно, не стесняйтесь задавать связанные (!) дополнительные вопросы.

...