测试

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.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@WebMvcTest(UserController.class)
class MySecurityTests {

	@Autowired
	private MockMvc mvc;

	@Test
	@WithMockUser(roles = "ADMIN")
	void requestProtectedUrlWithUser() throws Exception {
		this.mvc.perform(get("/"));
	}

}
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.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders

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

	@Test
	@WithMockUser(roles = ["ADMIN"])
	fun requestProtectedUrlWithUser() {
		mvc.perform(MockMvcRequestBuilders.get("/"))
	}

}

Spring Security 与 Spring MVC Test 进行了全面集成,这也可以在使用 @WebMvcTest 切片和 MockMvc 测试控制器时使用。

有关 Spring Security 测试支持的更多详细信息,请参阅 Spring Security 的 参考文档

在切片测试中包含 @Configuration

切片测试通过将 Spring 框架的组件扫描限制在基于组件类型的有限集合来工作。对于任何不是通过组件扫描创建的 Bean,例如使用 @Bean 注解创建的 Bean,切片测试将无法将它们包含在或排除在应用程序上下文中。请考虑以下示例

import org.apache.commons.dbcp2.BasicDataSource;

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 BasicDataSource secondDataSource() {
		return DataSourceBuilder.create().type(BasicDataSource.class).build();
	}

}

对于具有上述 @Configuration 类的应用程序的 @WebMvcTest,您可能希望在应用程序上下文中拥有 SecurityFilterChain Bean,以便您可以测试您的控制器端点是否已正确保护。但是,MyConfiguration 不会被 @WebMvcTest 的组件扫描过滤器拾取,因为它与过滤器指定的任何类型都不匹配。您可以通过使用 @Import(MyConfiguration.class) 注解测试类来显式包含配置。这将加载 MyConfiguration 中的所有 Bean,包括 BasicDataSource Bean,该 Bean 在测试 Web 层时不需要。将配置类拆分为两个将使您能够仅导入安全配置。

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 org.apache.commons.dbcp2.BasicDataSource;

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 BasicDataSource secondDataSource() {
		return DataSourceBuilder.create().type(BasicDataSource.class).build();
	}

}

当某个域的 Bean 需要包含在切片测试中时,使用单个配置类可能效率低下。相反,将应用程序的配置结构化为多个细粒度的类,这些类包含特定域的 Bean,可以使您仅在特定切片测试中导入它们。