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?
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?
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.
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.
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();
}
}
}
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.