You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 09:57:36