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

如何使用JUnit5 Mock Spring Security的authentication.getAuthorities()方法?

JUnit5 Mock 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 17:15:45