How to unittest a class using RestTemplate offline?

后端 未结 4 592
南笙
南笙 2020-12-29 20:09

I have a class which has direct dependency on the RestTemplate. I wish I have a JUnit test of it, offline.

How could I mock a RestTemplate in my unittest?

相关标签:
4条回答
  • 2020-12-29 21:00

    You can use the Mock classes in package org.springframework.mock.web.

    Usually you will need MockHttpServletRequest and MockHttpServletResponse, but if you need more control you may also need others, e.g. MockRequestDispatcher.

    Both of these implement the corresponding Servlet interfaces but add convenience methods for testing (and, most importantly: they work without a real HTTP connection).

    You can find the Mock classes in the spring-test jar (accessible through Maven)


    Update: it seems that the above classes are no great help for RestTemplate after all. What you will need is to create a mock ClientHttpRequestFactory, and I'm surprised to see that there isn't one in the above package. Here is some code to get you started (haven't tested it):

    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();
            }
    
        }
    
    
    }
    
    0 讨论(0)
  • 2020-12-29 21:04

    spring-social-test contains mockup classes that help write tests for RestTemplate. There are also some examples on how to use it within the git repository (e.g. OAuth1TemplateTest).

    Please keep in mind that there's currently a Spring feature request (#SPR-7951) to move these classes to spring-web.

    0 讨论(0)
  • 2020-12-29 21:09

    Sping 3.0 introduced RestTemplate. Since version 3.2, the Spring MVC test framework has provided the class MockRestServiceServer for unit testing client REST code.

    0 讨论(0)
  • 2020-12-29 21:11

    I suggest refactoring your client code to remove the direct dependency on RestTemplate, and replace it with references to RestOperations, which is the interface implemented by RestTemplate. and the one you should be coding to.

    You can then inject a stub or mock of RestOperations into your code for unit testing, and inject a RestTemplate when using it for real.

    0 讨论(0)
提交回复
热议问题