此版本仍在开发中,尚未视为稳定版。如需最新稳定版本,请使用 Spring Boot 4.0.4spring-doc.cadn.net.cn

测试

Spring Boot 包含了多种测试工具和辅助类,以及一个专用的 starter,用于提供常见的测试依赖。 本节解答有关测试的常见问题。spring-doc.cadn.net.cn

使用 Spring Security 进行测试

Spring Security 提供了以特定用户身份运行测试的支持。 例如,下面代码片段中的测试将以拥有 ADMIN 角色的已认证用户身份运行。spring-doc.cadn.net.cn

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 Test 的全面集成,这也可以在使用 @WebMvcTest 切片和 MockMvc 测试控制器时使用。spring-doc.cadn.net.cn

有关 Spring Security 测试支持的更多详细信息,请参阅 Spring Security 的参考文档spring-doc.cadn.net.cn

结构@Configuration用于包含在切片测试中的类

切片测试通过将 Spring 框架的组件扫描限制为基于类型的有限组件集来工作。 对于任何未通过组件扫描创建的 Bean,例如使用 @Bean 注解创建的 Bean,切片测试将无法把它们包含或排除在应用上下文中。 请考虑以下示例:spring-doc.cadn.net.cn

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 类的应用程序,若要为其提供 @WebMvcTest,您可能会期望在应用程序上下文中存在 SecurityFilterChain bean,以便测试您的控制器端点是否已正确保护。 然而,MyConfiguration 未被 @WebMvcTest 的组件扫描过滤器捕获,因为它不匹配过滤器指定的任何类型。 您可以通过使用 @Import(MyConfiguration.class) 注解测试类来显式包含该配置。 这将加载 MyConfiguration 中的所有 bean,包括在测试 Web 层时并不需要的 HikariDataSource bean。 将配置类拆分为两个部分,将能够仅导入安全配置。spring-doc.cadn.net.cn

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,这样就可以只为特定的切片测试导入所需的配置。spring-doc.cadn.net.cn

降级 Testcontainers Docker API 版本

Docker Desktop 的最新版本不再支持 Spring Boot 所管理的 Testcontainers 依赖项使用的默认 API 版本。 为帮助避免相关问题,Spring Boot 在 docker-java.propertiesspring-boot-testcontainers 的 jar 包中附带了 spring-boot-test 文件,用于升级 Testcontainers 所使用的 API 版本。spring-doc.cadn.net.cn

如果你不希望 API 版本被更改,应在你自己的项目 classpath 中添加一个 docker-java.properties 文件。 一个空文件将恢复默认行为,或者你可以将 api.version 属性设置为你偏好的任意值。spring-doc.cadn.net.cn