此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.3! |
测试
Spring Boot 包括许多测试实用程序和支持类,以及一个提供常见测试依赖项的专用Starters。 本节回答有关测试的常见问题。
使用 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 provides comprehensive integration with Spring MVC Test, and this can also be used when testing controllers using the @WebMvcTest
slice and MockMvc
.
For additional details on Spring Security’s testing support, see Spring Security’s reference documentation.
Structure @Configuration
Classes for Inclusion in Slice Tests
Slice tests work by restricting Spring Framework’s component scanning to a limited set of components based on their type.
For any beans that are not created through component scanning, for example, beans that are created using the @Bean
annotation, slice tests will not be able to include/exclude them from the application context.
Consider this example:
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();
}
}
For a @WebMvcTest
for an application with the above @Configuration
class, you might expect to have the SecurityFilterChain
bean in the application context so that you can test if your controller endpoints are secured properly.
However, MyConfiguration
is not picked up by @WebMvcTest’s component scanning filter because it doesn’t match any of the types specified by the filter.
You can include the configuration explicitly by annotating the test class with @Import(MyConfiguration.class)
.
This will load all the beans in MyConfiguration
including the HikariDataSource
bean which isn’t required when testing the web tier.
Splitting the configuration class into two will enable importing just the security configuration.
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();
}
}
Having a single configuration class can be inefficient when beans from a certain domain need to be included in slice tests.
Instead, structuring the application’s configuration as multiple granular classes with beans for a specific domain can enable importing them only for specific slice tests.