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

如何为集成Spring Security的项目编写基于JUnit 5的单元测试?

方案说明

你当前的写法是否正确完全取决于你的测试目标,两种适配方案如下:

场景1:仅测试Controller层业务逻辑/接口权限规则,不需要验证自定义认证逻辑

这种场景下你现在的写法是完全合理的:@WebMvcTest 本身就是切片测试,默认只会加载指定Controller相关的Bean,你Mock掉AuthenticationService是为了避免依赖安全层的实现,只需要按测试场景Mock认证的返回结果即可:

  • 测试需要认证通过的场景:Mock authenticate 方法返回带对应角色权限的Authentication对象
  • 测试认证失败的场景:Mock authenticate 方法抛出AuthenticationException子类即可

场景2:需要将自定义AuthenticationProvider的认证逻辑也纳入测试范围

这种场景确实不该直接Mock AuthenticationService,你需要调整测试配置,引入安全配置类,只Mock AuthenticationService的底层依赖:

  1. 调整PortfolioControllerTest配置:
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
// 引入自定义的SecurityConfig配置类,避免被切片测试过滤
@WebMvcTest(value = PortfolioController.class, includeFilters = {
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
})
public class PortfolioControllerTest {

    @Autowired
    private MockMvc mvc;

    @Autowired
    private JacksonTester<Portfolio> json;

    @MockBean
    private UserService userService;

    @MockBean
    private PortfolioService portfolioService;

    // 不再Mock AuthenticationService,改为Mock它的两个底层依赖
    @MockBean
    private UserRepository userRepository;
    
    @MockBean
    private HashService hashService;

    // 测试方法里可以模拟userRepository、hashService的返回,验证真实的认证流程逻辑
}
  1. 单独为AuthenticationService编写单元测试(更推荐,完全不需要Spring上下文,执行速度更快)
@ExtendWith(MockitoExtension.class)
public class AuthenticationServiceTest {

    @Mock
    private UserRepository userRepository;
    
    @Mock
    private HashService hashService;

    @InjectMocks
    private AuthenticationService authenticationService;

    @Test
    public void authenticate_shouldReturnAuthenticatedToken_whenCredentialsValid() {
        // 构造入参UsernamePasswordAuthenticationToken
        // Mock userRepository.findByUsername返回匹配的用户实体
        // Mock hashService.matches返回密码匹配结果
        // 调用authenticate方法断言返回的认证对象符合预期
    }

    @Test
    public void authenticate_shouldThrowException_whenPasswordWrong() {
        // 测试密码错误的异常分支逻辑
    }

    @Test
    public void supports_shouldReturnTrue_forUsernamePasswordToken() {
        assertTrue(authenticationService.supports(UsernamePasswordAuthenticationToken.class));
    }
}

额外提示

如果你的测试不需要走完整的认证流程,只是要模拟某个已登录用户访问接口,可以直接用Spring Security提供的@WithMockUser注解修饰测试方法,指定用户名、角色即可,不需要手动Mock任何认证相关的Bean。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 16:00:04