Как протестировать класс с помощью RestTemplate в автономном режиме?

У меня есть класс, который имеет прямую зависимость от RestTemplate. Я бы хотел, чтобы у меня был тест JUnit в автономном режиме.

Как я могу издеваться над RestTemplate в своем модульном тесте?


person Dennis C    schedule 10.01.2011    source источник
comment
Посмотрите мой ответ здесь stackoverflow.com/a/22334918/1077708   -  person vincentjames501    schedule 11.03.2014


Ответы (4)


Я предлагаю реорганизовать ваш клиентский код, чтобы удалить прямую зависимость от RestTemplate и заменить ее ссылками на RestOperations, который представляет собой интерфейс, реализованный RestTemplate. и тот, на который вы должны кодировать.

Затем вы можете внедрить заглушку или макет RestOperations в свой код для модульного тестирования и внедрить RestTemplate при его реальном использовании.

person skaffman    schedule 10.01.2011
comment
То, что сказал г-н @skaffman, в целом верно и правильно. Тем не менее, я должен отметить, что RestTemplate используется практически ВЕЗДЕ, где Google приведет вас, даже MockRestServiceServer (как указал @Raedwald). Кроме того, документация Javadoc для состояния RestOperations нечасто используется напрямую, но является полезной опцией для улучшения тестируемости, поскольку ее можно легко имитировать или заглушить. - person demaniak; 15.03.2016
comment
Дополнительный вопрос: если вы используете RestOperations, а экземпляр потребляется реализацией Service (тестируемый класс), как бы вы поместили фиктивный экземпляр RestOperations в службу? Создать экземпляр службы непосредственно в тесте и использовать установщик? - person demaniak; 15.03.2016
comment
В наши дни очень легко смоделировать RestTemplate, но довольно сложно реализовать все RestOperations многие методы. - person Michael Piefel; 12.07.2016

В версии Spring 3.0 представлено RestTemplate. Начиная с версии 3.2, Spring Платформа тестирования MVC предоставила класс MockRestServiceServer для модульного тестирования REST-кода клиента.

person Raedwald    schedule 12.09.2013
comment
Доступен ли он на Android? - person Piotr; 15.02.2014
comment
@Piotr, у меня это работает с gradle: androidTestCompile(org.springframework:spring-test:3.2.8.RELEASE) { exclude module: spring-core} - person vincentjames501; 11.03.2014

Вы можете использовать классы Mock в пакете org.springframework.mock.web.

Обычно вам потребуется MockHttpServletRequest и MockHttpServletResponse, но если вам нужно больше контроля, вам также могут понадобиться другие, например. MockRequestDispatcher.

Оба они реализуют соответствующие интерфейсы сервлетов, но добавляют удобные методы для тестирования (и, что наиболее важно: они работают без реального HTTP-соединения).

Вы можете найти классы Mock в jar-файле spring-test (доступном через Maven )


Обновление: кажется, что приведенные выше классы не очень помогают для RestTemplate. Вам потребуется создать макет ClientHttpRequestFactory, и я удивлен, увидев, что в приведенном выше пакете его нет. Вот код для начала (не проверял):

public class MockClientHttpRequestFactory implements
    ClientHttpRequestFactory{

    // overwrite this if you want
    protected MockClientHttpResponse createResponse(){
        return new MockClientHttpResponse();
    }

    // or this
    protected HttpStatus getHttpStatusCode(){
        return HttpStatus.OK;
    }

    // or even this
    @Override
    public ClientHttpRequest createRequest(final URI uri,
        final HttpMethod httpMethod) throws IOException{
        return new MockClientHttpRequest(uri, httpMethod);
    }

    public class MockClientHttpResponse implements ClientHttpResponse{
        private final byte[] data = new byte[10000];
        private final InputStream body = new ByteArrayInputStream(data);
        private final HttpHeaders headers = new HttpHeaders();
        private HttpStatus status;

        @Override
        public InputStream getBody() throws IOException{
            return body;
        }

        @Override
        public HttpHeaders getHeaders(){
            return headers;
        }

        @Override
        public HttpStatus getStatusCode() throws IOException{
            return getHttpStatusCode();
        }

        @Override
        public String getStatusText() throws IOException{
            return status.name();
        }

        @Override
        public void close(){
            try{
                body.close();
            } catch(final IOException e){
                throw new IllegalStateException(e);
            }

        }

    }

    class MockClientHttpRequest implements ClientHttpRequest{

        private final HttpHeaders headers = new HttpHeaders();
        private final HttpMethod method;
        private final URI uri;
        private final OutputStream body = new ByteArrayOutputStream();

        MockClientHttpRequest(final URI uri, final HttpMethod httpMethod){
            this.uri = uri;
            method = httpMethod;

        }

        @Override
        public OutputStream getBody() throws IOException{
            return body;
        }

        @Override
        public HttpHeaders getHeaders(){
            return headers;
        }

        @Override
        public HttpMethod getMethod(){
            return method;
        }

        @Override
        public URI getURI(){
            return uri;
        }

        @Override
        public ClientHttpResponse execute() throws IOException{
            return createResponse();
        }

    }


}
person Sean Patrick Floyd    schedule 10.01.2011
comment
Ты не ответил на мой вопрос. Ваше решение помогает в тестировании сервлета на стороне сервера, инфраструктуры MVC. Я собираюсь протестировать клиентскую часть, использующую фреймворк MVC. - person Dennis C; 10.01.2011
comment
Это именно то, что мне нужно для одного из моих проектов REST. Большое спасибо. - person Elwood; 05.12.2011
comment
(+1) идея работает. Но у меня такое ощущение, что два метода getStatusCode и getStatusText в MockClientHttpResponse немного страдают шизофренией. Пусть getStatusText(){return this.getStatusCode().name();} исцелит их. ;-) - person Ralph; 08.02.2012
comment
@SeanPatrickFloyd У меня также есть аналогичный вопрос здесь, который использует RestTemplate, посмотрите, можете ли вы мне помочь вон если можно. Любая помощь будет оценена. - person AKIWEB; 07.09.2014

spring-social-test содержит макеты классов, которые помогают писать тесты для RestTemplate. Есть также несколько примеров того, как использовать его в репозитории git (например, OAuth1TemplateTest).

Имейте в виду, что в настоящее время существует запрос функции Spring (#SPR-7951) для перемещения эти классы в spring-web.

person Gerhard Schlager    schedule 20.04.2011
comment
Это очень полезно для тестирования остальных клиентов. - person Johan Sjöberg; 17.01.2012