Spring Boot带Security的集成测试返回401问题求助
问题原因与解决方案
你遇到的核心问题是:@WithMockUser/@WithAnonymousUser这类注解只对MockMvc生效,而TestRestTemplate发起的是真实HTTP请求,服务器端的Security上下文和测试类的上下文是独立的,所以这些注解无法为真实请求注入认证信息,导致返回401。
下面是几种可行的解决办法:
方法一:给TestRestTemplate添加HTTP Basic认证
因为你的Security配置用了HttpBasic认证,所以可以直接在请求时带上用户名和密码:
方式1:全局配置TestRestTemplate
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc public class EmployeeControllerIntegrationTest { @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; // 在测试前配置认证信息 @BeforeEach void setUp() { // 替换成你测试用的用户名和密码 restTemplate = restTemplate.withBasicAuth("testuser", "testpassword"); } @Test public void test_Get_200() throws Exception { ResponseEntity<?> response = this.restTemplate.getForEntity( "http://localhost:" + port + "/employee", List.class ); assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); } }
方式2:单个请求指定认证
@Test public void test_Get_200() throws Exception { ResponseEntity<?> response = this.restTemplate.withBasicAuth("testuser", "testpassword") .getForEntity("http://localhost:" + port + "/employee", List.class); assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); }
注意:你需要确保测试环境存在对应的用户,可以通过测试专用的UserDetailsService配置来添加(见方法二)。
方法二:添加测试专用的用户配置
创建一个仅在测试时生效的Security配置类,注入测试用的内存用户:
@TestConfiguration public class TestSecurityConfig { @Bean public UserDetailsService userDetailsService() { // 创建测试用户,{noop}表示不加密密码(仅测试用) UserDetails testUser = User.withUsername("testuser") .password("{noop}testpassword") .roles("USER") .build(); return new InMemoryUserDetailsManager(testUser); } }
然后在测试类中引入这个配置:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @Import(TestSecurityConfig.class) // 引入测试配置 public class EmployeeControllerIntegrationTest { // ... 原有代码不变,配合方法一的认证逻辑使用 }
方法三:改用MockMvc测试(推荐)
如果不需要测试真实的HTTP请求,改用MockMvc可以直接利用@WithMockUser注解,更简洁:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class EmployeeControllerIntegrationTest { @Autowired private MockMvc mockMvc; @Test @WithMockUser(username = "testuser", roles = {"USER"}) public void test_Get_200() throws Exception { mockMvc.perform(get("/employee")) .andExpect(status().isOk()); } }
这种方式不需要处理端口,@WithMockUser会直接模拟认证用户,Security上下文会正确识别。
内容的提问来源于stack exchange,提问作者noxteryn
相关产品推荐
相关产品推荐

