CodeGym /Courses /Module 5. Spring /Testing Tools

Testing Tools

Module 5. Spring
Level 15 , Lesson 13
Available

ConfigDataApplicationContextInitializer

ConfigDataApplicationContextInitializer is an ApplicationContextInitializer that can be applied to tests to load application.properties files for Spring Boot. You can use it if you do not need the full set of functions provided by the @SpringBootTest annotation, as shown in the following example:

Java
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; @ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class) class MyConfigFileTests { // ... } 
Kotlin
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer import org.springframework.test.context.ContextConfiguration @ContextConfiguration(classes = [Config::class], initializers = [ConfigDataApplicationContextInitializer::class]) class MyConfigFileTests { // ... } 
Using solely the ConfigDataApplicationContextInitializer class will not provide support for embedding the @Value("${...​}") annotation . Its only job is to ensure that the application.properties files are loaded into the Environment for Spring. To support the @Value annotation, you must either additionally configure the PropertySourcesPlaceholderConfigurer, or use the @SpringBootTest annotation, which will automatically configure it for you.

TestPropertyValues

The Class TestPropertyValues allows you to quickly add properties to a ConfigurableEnvironment or ConfigurableApplicationContext. You can call it using the lines key=value, as shown below:

Java
import org.junit.jupiter.api.Test; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; class MyEnvironmentTests { @Test void testPropertySources() { MockEnvironment environment = new MockEnvironment(); TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment); assertThat(environment.getProperty("name")).isEqualTo("Boot"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.boot.test.util.TestPropertyValues import org.springframework.mock.env.MockEnvironment class MyEnvironmentTests { @Test fun testPropertySources() { val environment = MockEnvironment() TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment) assertThat(environment.getProperty("name")).isEqualTo("Boot") } } 

OutputCapture

OutputCapture is an Extension for JUnit that can be used to capture the output of System.out and System.err. To use, add the @ExtendWith(OutputCaptureExtension.class) annotation and inject CapturedOutput as an argument in your test class constructor or test method like this:

Java
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(OutputCaptureExtension.class) class MyOutputCaptureTests { @Test void testName(CapturedOutput output) { System.out.println("Hello World!"); assertThat(output).contains("World"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.boot.test.system.CapturedOutput import org.springframework.boot.test.system.OutputCaptureExtension @ExtendWith(OutputCaptureExtension::class) class MyOutputCaptureTests { @Test fun testName(output: CapturedOutput?) { println("Hello World!") assertThat(output).contains("World") } } 

TestRestTemplate

TestRestTemplate is a convenient alternative to Spring's RestTemplate that is useful for integration tests. You can get a vanilla template or one that sends basic HTTP authentication (with username and password). In any case, the template is fault-tolerant. This means that its operating logic is convenient for testing and does not generate exceptions for errors 4xx and 5xx. Instead, such errors can be detected through the returned ResponseEntity and its status code.

Spring Framework 5.0 includes a new WebTestClient that is also good for integration tests in WebFlux, and for end-to-end testing in WebFlux and MVC. Unlike TestRestTemplate, it provides a fluid API for adding assertions.

It is recommended - although not required - to use the Apache HTTP Client (version 4.3.2 or higher). If it is in your classpath, the TestRestTemplate template will respond to this and configure the client accordingly. If you are using the Apache HTTP client, some additional features are added that are useful for testing:

  • Redirects are not tracked (so you can add claims for the response location).

  • Cookies are ignored (so the template does not save state).

An instance of TestRestTemplate can be created directly in integration tests, as shown in the following example:

Java
import org.junit.jupiter.api.Test; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; class MyTests { private final TestRestTemplate template = new TestRestTemplate(); @Test void testRequest() { ResponseEntity<String> headers = this.template.getForEntity("https://myhost.example.com/example", String.class); assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.boot.test.web.client.TestRestTemplate class MyTests { private val template = TestRestTemplate() @Test fun testRequest() { val headers = template.getForEntity("https://myhost.example.com/example", String::class.java) assertThat(headers.headers.location).hasHost("other.example.com") } } 

Additionally, if you use the @SpringBootTest annotation with WebEnvironment.RANDOM_PORT or WebEnvironment.DEFINED_PORT, you can inject a fully configured TestRestTemplate and start using it. If necessary, additional settings can be applied via the RestTemplateBuilder bean. Any URLs that do not specify a host and port are automatically connected to the built-in server, as shown in the following example:

Java
import java.time.Duration; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MySpringBootTests { @Autowired private TestRestTemplate template; @Test void testRequest() { HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders(); assertThat(headers.getLocation()).hasHost("other.example.com"); } @TestConfiguration(proxyBeanMethods = false) static class RestTemplateBuilderConfiguration { @Bean RestTemplateBuilder restTemplateBuilder() { return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1)) .setReadTimeout(Duration.ofSeconds(1)); } } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.SpringBootTest.WebEnvironment import org.springframework.boot.test.context.TestConfiguration import org.springframework.boot.test.web.client.TestRestTemplate import org.springframework.boot.web.client.RestTemplateBuilder import org.springframework.context.annotation.Bean import java.time.Duration @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MySpringBootTests(@Autowired val template: TestRestTemplate) { @Test fun testRequest() { val headers = template.getForEntity("/example", String::class.java).headers assertThat(headers.location).hasHost("other.example.com") } @TestConfiguration(proxyBeanMethods = false) internal class RestTemplateBuilderConfiguration { @Bean fun restTemplateBuilder(): RestTemplateBuilder { return RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1)) .setReadTimeout(Duration.ofSeconds(1)) } } } 
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION