テストユーティリティ

アプリケーションのテスト時に一般的に役立ついくつかのテストユーティリティクラスは、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) の便利な代替手段であり、統合テストで役立ちます。spring-boot-resttestclient モジュールによって提供されます。spring-boot-restclient への依存関係も必要です。この依存関係を追加する際は、RestClient.Builder の自動構成が有効になるため注意してください。メインコードで RestClient.Builder を使用している場合は、spring-boot-restclient 依存関係をアプリケーションのテストクラスパスだけでなくメインクラスパスにも宣言してください。

標準のテンプレート、または Basic HTTP 認証(ユーザー名とパスワードを使用)を送信するテンプレートを入手できます。どちらの場合も、テンプレートはフォールトトレラントです。つまり、4xx エラーや 5xx エラーが発生した場合に例外をスローしないため、テストに適した動作をします。代わりに、返される ResponseEntity (Javadoc) とそのステータスコードによって、これらのエラーを検出できます。

アサーション用の流れるような API が必要な場合は、モック環境エンドツーエンドテストで機能する RestTestClient (Javadoc) の使用を検討してください。

Spring、WebFlux を使用している場合は、同様の API を提供し、モック環境WebFlux 統合テストエンドツーエンドテストで動作する WebTestClient (Javadoc) を検討してください。

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.resttestclient.TestRestTemplate;
import org.springframework.http.HttpStatus;
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> response = this.template.getForEntity("https://myhost.example.com/example",
				String.class);
		assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
		// Other assertions to verify the response
	}

}
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.boot.resttestclient.TestRestTemplate
import org.springframework.http.HttpStatus

class MyTests {

	private val template = TestRestTemplate()

	@Test
	fun testRequest() {
		val response = template.getForEntity("https://myhost.example.com/example", String::class.java)
		assertThat(response.statusCode).isEqualTo(HttpStatus.OK)
		// Other assertions to verify the response
	}

}

あるいは、@SpringBootTest (Javadoc) アノテーションを WebEnvironment.RANDOM_PORT または WebEnvironment.DEFINED_PORT と組み合わせて使用する場合、テストクラスに @AutoConfigureTestRestTemplate (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.restclient.RestTemplateBuilder;
import org.springframework.boot.resttestclient.TestRestTemplate;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;
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.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureTestRestTemplate
class MySpringBootTests {

	@Autowired
	private TestRestTemplate template;

	@Test
	void testRequest() {
		ResponseEntity<String> response = this.template.getForEntity("/example", String.class);
		assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
		// Other assertions to verify the response
	}

	@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.restclient.RestTemplateBuilder
import org.springframework.boot.resttestclient.TestRestTemplate
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate
import org.springframework.context.annotation.Bean
import org.springframework.http.HttpStatus
import java.time.Duration

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureTestRestTemplate
class MySpringBootTests(@Autowired val template: TestRestTemplate) {

	@Test
	fun testRequest() {
		val response = template.getForEntity("/example", String::class.java)
		assertThat(response.statusCode).isEqualTo(HttpStatus.OK)
		// Other assertions to verify the response
	}

	@TestConfiguration(proxyBeanMethods = false)
	internal class RestTemplateBuilderConfiguration {

		@Bean
		fun restTemplateBuilder(): RestTemplateBuilder {
			return RestTemplateBuilder().connectTimeout(Duration.ofSeconds(1))
				.readTimeout(Duration.ofSeconds(1))
		}

	}

}