在Spring Boot 4.x中,与安全相关的行为与Spring Boot 3.x相比存在差异
根据我的观察更新了问题。
我在尝试理解Spring Security,在实现带有 @WebMvcTest 的测试时陷入困境。
我有一个Spring Boot 4.0.3项目,包含 spring-boot-starter-webmvc, spring-boot-starter-webmvc-test, spring-boot-starter-security 依赖。
spring-boot-starter-security-test 未包含。
没有与安全相关的配置。
下面是下方的REST控制器。
@RestController
public class DemoController {
@GetMapping("/hello")
public String hello() {
return "Hello";
}
}
下面是测试类。
@WebMvcTest(DemoController.class)
@AutoConfigureRestTestClient
class DemoControllerTest {
@Autowired
private RestTestClient restClient;
@Autowired
private MockMvc mockMvc;
@Autowired
private MockMvcTester mockMvcTester;
@Test
void test_hello_001() {
restClient.get()
.uri("/hello")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Hello");
}
@Test
void test_hello_002() {
Assertions.assertThat(mockMvcTester.get()
.uri("/hello"))
.hasStatusOk()
.hasBodyTextEqualTo("Hello");
}
@Test
void test_hello_003() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.status()
.isOk())
.andExpect(MockMvcResultMatchers.content()
.string("Hello"));
}
}
我还有一个Spring Boot 3.5.11项目,包含 spring-boot-starter-web, spring-boot-starter-test, spring-boot-starter-security 依赖。
spring-security-test 未包含。
没有与安全相关的配置。
下面是REST控制器。
@RestController
public class DemoController {
@GetMapping("/hello")
public String hello() {
return "Hello";
}
}
下面是测试类。
@WebMvcTest(DemoController.class)
// @AutoConfigureRestTestClient
class DemoControllerTest {
// @Autowired
// private RestTestClient restClient;
@Autowired
private MockMvc mockMvc;
@Autowired
private MockMvcTester mockMvcTester;
// @Test
// void test_hello_001() {
// restClient.get()
// .uri("/hello")
// .exchange()
// .expectStatus()
// .isOk()
// .expectBody(String.class)
// .isEqualTo("Hello");
// }
@Test
void test_hello_002() {
Assertions.assertThat(mockMvcTester.get()
.uri("/hello"))
.hasStatusOk()
.hasBodyTextEqualTo("Hello");
}
@Test
void test_hello_003() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.status()
.isOk())
.andExpect(MockMvcResultMatchers.content()
.string("Hello"));
}
}
test_hello_001 已被注释,因为 RestTestClient 不可用。
第一个项目(4.0.3)的测试在没有 @WithMockUser 或任何自定义安全配置的情况下通过。
当我在pom.xml中引入 spring-boot-starter-security-test 依赖时,测试会出现如下消息:
java.lang.AssertionError: Status expected:<200 OK> but was:<401 UNAUTHORIZED>
Expected :200 OK
Actual :401 UNAUTHORIZED
第二个项目(3.5.11)的测试无论有无 spring-security-test 依赖都会失败。
对于第二个项目(3.5.11)的测试失败,这对我来说是合理的,添加 @WithMockUser 可以修复它。但为什么同样的测试在第一个项目(4.0.3)在没有 @WithMockUser 的情况下通过,添加 spring-boot-starter-security-test 依赖后就会失败呢。
解决方案
引入 spring-boot-starter-security-test 将最终拉入 spring-boot-security-test 模块。该模块包含安全部分的所有测试自动配置。
具体用于与 integration with @WebMvcTest 的集成。这些includes将在启动应用进行测试时引导安全部分。没有它,@WebMvcTest 就不会配置安全,因此测试将直接通过。