How to configure Spring TestRestTemplate

Robert picture Robert · Feb 16, 2017 · Viewed 12.5k times · Source

I have a REST (spring-hateoas) server that I'd like to test with a JUnit test. Therefore I am using an autoinjected TestRestTemplate.

But how do I now add some more configuration to this pre configured TestRestTemplate? I need to configure the rootURI and add interceptors.

Thisi s my JUnit Test class:

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)      

public class RestEndpointTests {
  private Logger log = LoggerFactory.getLogger(this.getClass());

  @LocalServerPort
  int localServerPort;

  @Value(value = "${spring.data.rest.base-path}")   // nice trick to get basePath from application.properties
  String basePath;

  @Autowired
  TestRestTemplate client;    //  how to configure client?

  [... here are my @Test methods that use client ...]
}

The documentation sais that a static @TestConfiguration class can be used. But inside that static class I cannot access localServerPort or basePath:

  @TestConfiguration
  static class Config {

    @Bean
    public RestTemplateBuilder restTemplateBuilder() {
      String rootUri = "http://localhost:"+localServerPort+basePath;    // <=== DOES NOT WORK
      log.trace("Creating and configuring RestTemplate for "+rootUri);
      return new RestTemplateBuilder()
        .basicAuthorization(TestFixtures.USER1_EMAIL, TestFixtures.USER1_PWD)
        .errorHandler(new LiquidoTestErrorHandler())
        .requestFactory(new HttpComponentsClientHttpRequestFactory())
        .additionalInterceptors(new LogRequestInterceptor())
        .rootUri(rootUri);
    }

  }

My most important question: Why doesn't TestRestTemplate take spring.data.rest.base-path from application.properties into account in the first place? Isn't the idea of beeing complete preconfigured, the whole use case of this wrapper class?

The doc sais

If you are using the @SpringBootTest annotation, a TestRestTemplate is automatically available and can be @Autowired into you test. If you need customizations (for example to adding additional message converters) use a RestTemplateBuilder @Bean.

How does that look like in a complete Java code example?

Answer

joensson picture joensson · May 1, 2017

I know this is an old question, and you have probably found another solution for this by now. But I'm answering anyway for others stumbling on it like I did. I had a similar problem and ended up using @PostConstruct in my test class for constructing a TestRestTemplate configured to my liking instead of using @TestConfiguration.

    @RunWith(SpringJUnit4ClassRunner.class)
    @EnableAutoConfiguration
    @SpringBootTest(classes = {BackendApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class MyCookieClientTest {
        @LocalServerPort
        int localPort;

        @Autowired
        RestTemplateBuilder restTemplateBuilder;

        private TestRestTemplate template;

        @PostConstruct
        public void initialize() {
            RestTemplate customTemplate = restTemplateBuilder
                .rootUri("http://localhost:"+localPort)
                ....
                .build();
            this.template = new TestRestTemplate(customTemplate,
                 null, null, //I don't use basic auth, if you do you can set user, pass here
                 HttpClientOption.ENABLE_COOKIES); // I needed cookie support in this particular test, you may not have this need
        }
    }