Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enabling Cookies and Redirects in TestRestTemplate

How to I add TestRestTemplate.HttpClientOption.ENABLE_REDIRECTS and TestRestTemplate.HttpClientOption.ENABLE_COOKIES to spring-boots TestRestTemplate?

I am using spring-boot so have a TestRestTemplate configured for me automatically.

I can customise this bean before creation using RestTemplateBuilder. The problem is I can't see how to add these options:

    @Bean
    public RestTemplateBuilder restTemplateBuilder() {
        return new RestTemplateBuilder()
                .errorHandler(new ResponseErrorHandler() {
                    ...
                });
    } 

The documentation has some constructors that accept these options but the problem is the bean has already been created for me.

like image 672
jax Avatar asked Oct 28 '25 13:10

jax


1 Answers

You can create a TestRestTemplate and present it to Spring by using the @Bean annotation.

For example:

@Bean
@Primary
public TestRestTemplate testRestTemplate() {
    RestTemplate restTemplate = new RestTemplateBuilder()
            .errorHandler(new ResponseErrorHandler() {
                @Override
                public boolean hasError(ClientHttpResponse response) throws IOException {
                    return false;
                }

                @Override
                public void handleError(ClientHttpResponse response) throws IOException {

                }
            }).build();

    return new TestRestTemplate(restTemplate, user, password, TestRestTemplate.HttpClientOption.ENABLE_REDIRECTS, TestRestTemplate.HttpClientOption.ENABLE_COOKIES);
}

Or, if you do not need to customise the RestTemplate then use the following constructor (which internally instances a RestTemplate for you):

@Bean
@Primary
public TestRestTemplate testRestTemplate() {
    return new TestRestTemplate(TestRestTemplate.HttpClientOption.ENABLE_REDIRECTS, TestRestTemplate.HttpClientOption.ENABLE_COOKIES);
}

Update 1 to address this comment:

when I run my tests, I now get the following error org.apache.http.ProtocolException: Target host is not specified

The TestRestTemplate provided by Spring is configured to resolve paths relative to http://localhost:${local.server.port}. So, when you replace the Spring provided instance with your own instance you'll either have to provide the full address (including host and port) or configure your own TestRestTemplate with a LocalHostUriTemplateHandler (you can see this code in org.springframework.boot.test.context.SpringBootTestContextCustomizer.TestRestTemplateFactory). Here's an example of the latter approach:

@Bean
@Primary
public TestRestTemplate testRestTemplate(ApplicationContext applicationContext) {
    RestTemplate restTemplate = new RestTemplateBuilder()
            .errorHandler(new ResponseErrorHandler() {
                @Override
                public boolean hasError(ClientHttpResponse response) throws IOException {
                    return false;
                }

                @Override
                public void handleError(ClientHttpResponse response) throws IOException {

                }
            }).build();

    TestRestTemplate testRestTemplate =
            new TestRestTemplate(restTemplate, user, password, TestRestTemplate.HttpClientOption
                    .ENABLE_REDIRECTS, TestRestTemplate.HttpClientOption.ENABLE_COOKIES);

    // let this testRestTemplate resolve paths relative to http://localhost:${local.server.port}
    LocalHostUriTemplateHandler handler =
            new LocalHostUriTemplateHandler(applicationContext.getEnvironment(), "http");
    testRestTemplate.setUriTemplateHandler(handler);

    return testRestTemplate;
}

With this bean configuration the following test case uses the customised TestRestTemplate and successfully invokes the Spring Boot app on localhost:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class RestTemplateTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void test() {
        ResponseEntity<String> forEntity = this.restTemplate.getForEntity("/some/endpoint", String.class);
        System.out.println(forEntity.getBody());
    }
}
like image 127
glytching Avatar answered Oct 31 '25 03:10

glytching



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!