Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Spring TestRestTemplate

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?

like image 206
Robert Avatar asked Feb 16 '17 11:02

Robert


2 Answers

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
        }
    }
like image 128
joensson Avatar answered Sep 28 '22 07:09

joensson


In order to configure your TestRestTemplate, the official documentation suggests you to use the TestRestTemplate, as shown in the example below (for example, to add a Basic Authentication):

public class YourEndpointClassTest {
    private static final Logger logger = LoggerFactory.getLogger(YourEndpointClassTest.class);  

    private static final String BASE_URL = "/your/base/url";

    @TestConfiguration
    static class TestRestTemplateAuthenticationConfiguration {

        @Value("${spring.security.user.name}")
        private String userName;

        @Value("${spring.security.user.password}")
        private String password;

        @Bean
        public RestTemplateBuilder restTemplateBuilder() {
            return new RestTemplateBuilder().basicAuthentication(userName, password);
        }
    }


    @Autowired
    private TestRestTemplate restTemplate;

//here add your tests...
like image 37
dcormar Avatar answered Sep 28 '22 06:09

dcormar