DEV Community

Shriharsh
Shriharsh

Posted on

Today I Learned: To use custom ClientHttpRequestFactory with MockRestServiceServer

Despite having some reservations about using Spring RestTemplate for writing JAX-RS client (see here), I chose to use Spring RestTemplate to implement a JAX RS client as I liked that I could write test cases by easily mocking the REST service I was consuming. Spring provides a very nice utility to mock REST service end-point: MockRestServiceServer. However, I ran into an pesky issue.

Problem

I developed my code along with the test cases using the above nice utility by Spring framework. Next step was to log all incoming and outgoing traffic. I was able to implement the feature by registering a custom LoggingInterceptor along with the BufferingClientHttpRequestFactory. The logging worked fine but my test cases started to fail. Although I ensured that I use BufferingClientHttpRequestFactory so that the response from the server can be read twice - once for logging and next by the application code, the test code would fail on the second read.

Diagnosis

I found that the MockRestServiceServer would override the BufferingClientHttpRequestFactory setup on the RestTemplate instance passed to it while creating the server.

@Override
public MockRestServiceServer build(RequestExpectationManager manager) {
    MockRestServiceServer server = new MockRestServiceServer(manager);
    MockClientHttpRequestFactory factory = server.new MockClientHttpRequestFactory();
    if (this.restTemplate != null) {
        this.restTemplate.setRequestFactory(factory);
    }
    if (this.asyncRestTemplate != null) {
        this.asyncRestTemplate.setAsyncRequestFactory(factory);
    }
    return server;
}

Enter fullscreen mode Exit fullscreen mode

Solution

On scouring further, I found that the there is a hack to work around this issue. Once the server is created, read the requestFactory instance created by the MockRestServiceServer using ReflectionTestUtils on RestTemplate instance and wrap it up with BufferingClientHttpRequestFactory.

@Before
public void setUp() throws Exception {
    mockServer = MockRestServiceServer.createServer(restTemplate);

    final ClientHttpRequestFactory requestFactory = 
        (ClientHttpRequestFactory) ReflectionTestUtils.getField(restTemplate, "requestFactory");

    restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(requestFactory));
}

Enter fullscreen mode Exit fullscreen mode

I hope this helps you as well.

Top comments (2)

Collapse
 
ericathedev profile image
Erica Tanti

I use BufferingClientHttpRequestFactory so that the response from the server can be read twice - once for logging and next by the application code, the test code would fail on the second read.

This was happening to me when I removed BufferingClientHttpRequestFactory and I couldn't figure out what was happening. Thank you for explaining why!

Collapse
 
shriharshmishra profile image
Shriharsh

Welcome 😊