テストユーティリティ

アプリケーションのテスト時に一般的に役立ついくつかのテストユーティリティクラスは、spring-boot の一部としてパッケージ化されています。

ConfigDataApplicationContextInitializer

ConfigDataApplicationContextInitializer (Javadoc) は、テストに適用して Spring Boot application.properties ファイルをロードできる ApplicationContextInitializer (Javadoc) です。次の例に示すように、@SpringBootTest (Javadoc) が提供する機能の完全なセットが必要ない場合に使用できます。

  • Java

  • Kotlin

import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class)
class MyConfigFileTests {

	// ...

}
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer
import org.springframework.test.context.ContextConfiguration

@ContextConfiguration(classes = [Config::class], initializers = [ConfigDataApplicationContextInitializer::class])
class MyConfigFileTests {

	// ...

}
ConfigDataApplicationContextInitializer (Javadoc) のみを使用すると、@Value("${…​}") インジェクションはサポートされません。その唯一のロールは、application.properties ファイルが Spring の Environment (Javadoc) にロードされるようにすることです。@Value (Javadoc) をサポートするには、PropertySourcesPlaceholderConfigurer (Javadoc) を追加で構成するか、@SpringBootTest (Javadoc) を使用して自動的に構成する必要があります。

TestPropertyValues

TestPropertyValues (Javadoc) を使用すると、ConfigurableEnvironment (Javadoc) または ConfigurableApplicationContext (Javadoc) にプロパティをすばやく追加できます。次のように、key=value 文字列を使用して呼び出すことができます。

  • Java

  • Kotlin

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");
	}

}
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")
	}

}

OutputCaptureExtension

OutputCaptureExtension (Javadoc) は、System.out (標準 Javadoc) および System.err (標準 Javadoc) 出力をキャプチャーするために使用できる JUnit Extension (英語) です。これを使用するには、次のように、@ExtendWith(OutputCaptureExtension.class) を追加し、テストクラスのコンストラクターまたはテストメソッドに引数として CapturedOutput (Javadoc) を挿入します。

  • Java

  • Kotlin

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");
	}

}
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 (Javadoc) は、統合テストで役立つ、Spring の RestTemplate (Javadoc) の便利な代替手段です。バニラテンプレートまたは Basic HTTP 認証 (ユーザー名とパスワードを使用) を送信するテンプレートを入手できます。どちらの場合も、テンプレートはフォールトトレラントです。つまり、4xx および 5xx エラーで例外をスローしないことで、テストに適した方法で動作します。代わりに、返された ResponseEntity (Javadoc) とそのステータスコードを通じて、このようなエラーを検出できます。

Spring Framework 5.0 は、WebFlux 統合テストWebFlux および MVC のエンドツーエンドテストの両方で機能する新しい WebTestClient (Javadoc) を提供します。TestRestTemplate (Javadoc) とは異なり、アサーション用の流れるような API を提供します。

Apache HTTP クライアント(バージョン 5.1 以降)の使用を推奨しますが、必須ではありません。クラスパスに Apache HTTP クライアントが含まれている場合、TestRestTemplate (Javadoc) はクライアントを適切に設定することで対応します。Apache の HTTP クライアントを使用する場合は、Cookie を無視するように設定されています(そのため、テンプレートはステートレスです)。

次の例に示すように、TestRestTemplate (Javadoc) は統合テストで直接インスタンス化できます。

  • Java

  • Kotlin

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");
	}

}
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")
	}

}

あるいは、WebEnvironment.RANDOM_PORT または WebEnvironment.DEFINED_PORT とともに @SpringBootTest (Javadoc) アノテーションを使用すると、完全に構成された TestRestTemplate (Javadoc) を挿入して使用を開始できます。必要に応じて、RestTemplateBuilder (Javadoc) Bean を通じて追加のカスタマイズを適用できます。次の例に示すように、ホストとポートを指定しない URL は、自動的に組み込みサーバーに接続します。

  • Java

  • Kotlin

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().connectTimeout(Duration.ofSeconds(1)).readTimeout(Duration.ofSeconds(1));
		}

	}

}
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().connectTimeout(Duration.ofSeconds(1))
				.readTimeout(Duration.ofSeconds(1))
		}

	}

}