如何使用JUnit5 Mock Spring Security的authentication.getAuthorities()方法?
要成功Mock Authentication.getAuthorities(),你需要结合Mockito和Spring Security Test模拟SecurityContext环境,以下是具体实现步骤:
1. 确保依赖齐全
在pom.xml(或build.gradle)中引入必要依赖:
<!-- JUnit5 --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency> <!-- Mockito --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <!-- Spring Security Test --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <version>5.7.6</version> <scope>test</scope> </dependency>
2. 编写测试类
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import javax.servlet.FilterChain; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) public class JwtTokenGeneratorFilterTest { private JwtTokenGeneratorFilter filter; @Mock private HttpServletRequest request; @Mock private HttpServletResponse response; @Mock private FilterChain chain; @Mock private Authentication authentication; @Mock private SecurityContext securityContext; @BeforeEach void setUp() { filter = new JwtTokenGeneratorFilter(); // 将Mock的SecurityContext设置到SecurityContextHolder SecurityContextHolder.setContext(securityContext); // 让SecurityContext返回预设的Authentication when(securityContext.getAuthentication()).thenReturn(authentication); } @AfterEach void tearDown() { // 测试后清空SecurityContextHolder,避免影响其他测试 SecurityContextHolder.clearContext(); } @Test void doFilterInternal_WithValidAuthentication_ShouldGenerateJwt() throws Exception { // 1. 模拟UserVO及关联对象 UserVO userVO = mock(UserVO.class); User user = mock(User.class); UserDetail userDetail = mock(UserDetail.class); when(userDetail.getId()).thenReturn(1L); when(user.getUserDetail()).thenReturn(userDetail); when(userVO.getUser()).thenReturn(user); // 2. 模拟Authentication的Principal和用户名 when(authentication.getPrincipal()).thenReturn(userVO); when(authentication.getName()).thenReturn("test-user"); // 3. 模拟权限集合 GrantedAuthority authority1 = mock(GrantedAuthority.class); GrantedAuthority authority2 = mock(GrantedAuthority.class); when(authority1.getAuthority()).thenReturn("ROLE_ADMIN"); when(authority2.getAuthority()).thenReturn("PERMISSION_EDIT"); when(authentication.getAuthorities()).thenReturn(java.util.List.of(authority1, authority2)); // 调用过滤器方法 filter.doFilterInternal(request, response, chain); // 验证JWT是否被设置到响应头 verify(response).setHeader(eq("Authorization"), anyString()); // 验证FilterChain是否继续执行 verify(chain).doFilter(request, response); } }
关键说明
- SecurityContext模拟:通过设置Mock的SecurityContext,让
SecurityContextHolder.getContext().getAuthentication()返回预设的Authentication对象。 - 权限模拟:直接Mock
GrantedAuthority实例,设置getAuthority()返回预期的权限字符串,再将这些实例组成集合返回给authentication.getAuthorities()。 - 测试清理:在
@AfterEach中清空SecurityContextHolder,防止测试之间的状态污染。
如果要验证populateAuthorities的逻辑正确性,可以解析生成的JWT断言权限值:
// 在测试方法中捕获响应头的JWT并解析 ArgumentCaptor<String> jwtCaptor = ArgumentCaptor.forClass(String.class); verify(response).setHeader(eq("Authorization"), jwtCaptor.capture()); String jwt = jwtCaptor.getValue(); // 解析JWT Claims Claims claims = Jwts.parserBuilder() .setSigningKey(AppConstant.JWT_KEY.getBytes()) .build() .parseClaimsJws(jwt) .getBody(); String authorities = claims.get(AppConstant.AUTHORITIES, String.class); assertTrue(authorities.contains("ROLE_ADMIN")); assertTrue(authorities.contains("PERMISSION_EDIT"));
内容的提问来源于stack exchange,提问作者Shakthi
相关产品推荐
相关产品推荐

