Spring-boot: TestRestTemplate replaces custom HttpClients

Created on 22 Mar 2017  路  13Comments  路  Source: spring-projects/spring-boot

Spring-Boot version 1.5.2.RELEASE

Problem:
When apache httpclient jar is in the classpath, TestRestTemplate replaces any HttpClient set by the user in a RestTemplate. Alseo, since the field is final there's no way to change that, even with reflection.
See this https://github.com/spring-projects/spring-boot/blob/master/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java#L127-L130.

In my case, I am building a client for mutual authentication and some headers. However, the same applications uses httpclient for other integrations, not only that, previous tests were written in RestAssured which also includes that dependency.

Is it possible to remove that validation, make it optional or just apply it if there's no requestFactory set?

bug

Most helpful comment

@bvulaj Unfortunately we needed to introduce a breaking change so 2.0 was the only option.

All 13 comments

Yeah, that's a bit nasty. You might be able to change it back afterwards until we can find a better fix:

RestTemplate rt = new RestTemplate();
TestRestTemplate trt = new TestRestTemplate(rt);
rt.setRequestFactory(...);

That's true! I did not think of that way to undo it.

Thanks a lot.

It really is tricky and I think the current code is a bit wrong but I can't see a way to fix it without breaking backward compat.

So one thing we could do is check if there are any HttpClientOptions before overriding the factory. If there aren't any, let's go with whatever we have. Also, rather than creating an empty RestTemplate like we do if none is provided, let's use the builder internally so that we benefit from the same algorithm that detects the factory to use.

If we do that, TestRestTemplate now follow redirects all the sudden. This is because our override of the request factory checks if the redirect option is set and if it isn't then the flag is false. Long story short, TestRestTemplate does not follow redirect while a sample RestTemplate does.

I don't know at this point if those inconsistencies are made on purpose but surely deviating from RestTemplate default doesn't sound very good to me. Not overriding the factory if no options is provided is also a bit fragile because we override it again if SSL is configured for instance.

Along these lines, I'm having difficulty with redirects in TestRestTemplate. Using 1.5.3.RELEASE I do not get a redirect for 302 (which is good: my test is specifically checking for this status code), but with 2.0.0.M1 I am getting a redirect.

I hunted for some way to customize the injected TestRestTemplate bean (using the @SpringBootTest(webEnvironment = RANDOM_PORT) annotation), or to replace it with one customized to not redirect, but didn't find what I needed.

The current docs say TestRestTemplate should not redirect, but in my test it is:

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-rest-templates-test-utility

An example:

https://github.com/binkley/sproingk/commit/49456e50eb3c855ea6b284b9565337d593b63994

(See https://github.com/binkley/sproingk/blob/49456e50eb3c855ea6b284b9565337d593b63994/src/test/kotlin/hm/binkley/labs/GreetingControllerIT.kt#L140 and remove the @Disabled annotation.)

@binkley That sounds like a separate problem. Can you please open a new issue? AFAIK, both 1.5.3.RELEASE and 2.0.0.M1 will not follow a redirect as long as you have Apache's HTTP client on the class path.

@wilkinsona OK, filed #9410. I do not explicitly ask for Apache HTTP client in my classpath, relying on Spring Boot starter to handle this.

Maybe I'm missing something here, but #11872 removed all TestRestTemplate constructor variants using a RestTemplate argument. Is this issue gone, then?

No, it's still there. The private constructor will clobber any request factory that was configured via a RestTemplateBuilder.

So, the TL;DR; is to use a new builder in the new release?

Yes, we've removed all constructors accepting a RestTemplate argument - you can now use RestTemplateBuilder variants instead.

Am I right in assuming this issue was not resolved for 1.5.X? Autowiring TestRestTemplate into my integration tests, with a RestTemplateBuilder bean wired, still invokes a ctor that negates my customizations.

@bvulaj Unfortunately we needed to introduce a breaking change so 2.0 was the only option.

@philwebb Understood. Will use the workaround for now. Thanks for the response.

Was this page helpful?
0 / 5 - 0 ratings