如何为Spring Boot控制器测试添加Basic Auth认证?
引入spring-boot-starter-security依赖后,Spring Security默认会给所有接口添加认证拦截规则,你原有测试用例里的MockMvc请求没有携带Basic认证要求的身份凭证,请求会在到达控制器之前就被安全过滤器拦截,因此返回401未授权状态码,和业务控制器逻辑无关。
1. 修正测试框架注解兼容问题
你当前使用JUnit5,测试类上的@RunWith(SpringRunner.class)是JUnit4的专属注解,JUnit5下不需要这个注解(@SpringBootTest已经自带Spring测试扩展),直接删除该行即可,避免框架混用导致的兼容问题。
2. 给MockMvc请求添加Basic认证凭证
Spring Security测试模块(随security starter自动引入)提供了专门的请求构造工具,不需要手动拼接Authorization请求头,直接静态导入SecurityMockMvcRequestPostProcessors.httpBasic方法,在每个请求中添加认证信息即可。
以createBook_success测试方法为例,修改后的请求部分代码如下:
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; // ...其他代码 @Test public void createBook_success() throws Exception { Book book = Book.builder().name("Great book").author("Ivan") .pagesNumber(340).publisher("New Publisher").build(); BookDto dto = converter.toDto(book); given(bookController.createBook(dto)).willReturn(dto); mockMvc.perform(post("/api/books/create") .with(httpBasic("admin", "admin")) // 新增该行,携带Basic认证账号密码 .contentType(MediaType.APPLICATION_JSON).content(asJsonString(book))) .andExpect(status().isCreated()); }
剩下的getAllBooks_success、findByTitle_success方法同理,在mockMvc.perform()的参数链式调用中,加上.with(httpBasic("admin", "admin"))即可通过认证校验。
3. (可选)全局配置默认认证,减少重复代码
如果你的测试类所有用例都使用同一个认证身份,可以在测试类中配置MockMvc的默认请求规则,不用每个请求都重复写认证逻辑:
@Autowired private MockMvc mockMvc; @BeforeEach // JUnit5的初始化注解,替代JUnit4的@Before void setUpDefaultAuth() { mockMvc = mockMvc.defaultRequest( get("/").with(httpBasic("admin", "admin")) ); }
配置后该测试类下所有MockMvc请求默认都会携带admin的Basic认证信息。
- 若需要验证安全配置本身的有效性,可以保留不带认证的请求,断言返回401状态码即可
- 后续如果扩展了角色、权限控制逻辑,可以使用
@WithMockUser注解直接模拟对应权限的用户身份,不需要走真实的HTTP认证流程,更方便测试权限拦截逻辑 - 相关实现细节可以参考Spring Security官方参考文档的Testing章节,覆盖了所有安全场景下的MockMvc测试方法,不需要依赖第三方零散教程
内容的提问来源于stack exchange,提问作者iank

