テスト

Spring Boot には、多数のテストユーティリティとサポートクラス、および一般的なテストの依存関係を提供する専用のスターターが含まれています。このセクションでは、テストに関する一般的な質問に回答します。

Spring Security を使用したテスト

Spring Security は、特定のユーザーとしてテストを実行するためのサポートを提供します。例: 以下のスニペットのテストは、ADMIN ロールを持つ認証済みユーザーで実行されます。

  • Java

  • Kotlin

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.assertj.MockMvcTester;

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

@WebMvcTest(UserController.class)
class MySecurityTests {

	@Autowired
	private MockMvcTester mvc;

	@Test
	@WithMockUser(roles = "ADMIN")
	void requestProtectedUrlWithUser() {
		assertThat(this.mvc.get().uri("/")).doesNotHaveFailed();
	}

}
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.autoconfigure.web.servlet.WebMvcTest
import org.springframework.security.test.context.support.WithMockUser
import org.springframework.test.web.servlet.assertj.MockMvcTester

@WebMvcTest(UserController::class)
class MySecurityTests(@Autowired val mvc: MockMvcTester) {

	@Test
	@WithMockUser(roles = ["ADMIN"])
	fun requestProtectedUrlWithUser() {
		assertThat(mvc.get().uri("/"))
				.doesNotHaveFailed()
	}

}

Spring Security は Spring MVC テストとの包括的な統合を提供し、これは @WebMvcTest (Javadoc) スライスと MockMvc (Javadoc) を使用してコントローラーをテストするときにも使用できます。

Spring Security のテストサポートの詳細については、Spring Security のリファレンスドキュメントを参照してください。

スライステストに含める構造 @Configuration (Javadoc) クラス

スライステストは、Spring Framework のコンポーネントスキャンを、その型に基づいて限られたコンポーネントセットに制限することで機能します。コンポーネントスキャンによって作成されない Bean (たとえば、@Bean (Javadoc) アノテーションを使用して作成された Bean) の場合、スライステストでは、アプリケーションコンテキストに含めたり除外したりすることはできません。次の例を検討してください。

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
		return http.build();
	}

	@Bean
	@ConfigurationProperties("app.datasource.second")
	public HikariDataSource secondDataSource() {
		return DataSourceBuilder.create().type(HikariDataSource.class).build();
	}

}

上記の @Configuration (Javadoc) クラスを持つアプリケーションの @WebMvcTest (Javadoc) の場合、コントローラーのエンドポイントが適切に保護されているかどうかをテストできるように、アプリケーションコンテキストに SecurityFilterChain (Javadoc) Bean があることが期待されます。ただし、MyConfiguration は、フィルターで指定されたどの型にも一致しないため、@WebMvcTest のコンポーネントスキャンフィルターによって検出されません。テストクラスに @Import(MyConfiguration.class) のアノテーションを付けることで、構成を明示的に含めることができます。これにより、Web 層のテスト時に不要な HikariDataSource (英語) Bean を含む、MyConfiguration のすべての Bean がロードされます。構成クラスを 2 つに分割すると、セキュリティ構成のみをインポートできるようになります。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
		return http.build();
	}

}
import com.zaxxer.hikari.HikariDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDatasourceConfiguration {

	@Bean
	@ConfigurationProperties("app.datasource.second")
	public HikariDataSource secondDataSource() {
		return DataSourceBuilder.create().type(HikariDataSource.class).build();
	}

}

特定のドメインの Bean をスライステストに含める必要がある場合、単一の構成クラスでは効率が悪い場合があります。代わりに、特定のドメインの Bean を含む複数の細分化されたクラスとしてアプリケーションの構成を構造化することで、特定のスライステストにのみ Bean をインポートできるようになります。