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

Apache Shiro单元测试:checkPermission无视存根权限仍通过

解决Mockito模拟Shiro Subject时checkPermission不抛异常的问题

这个问题我刚接触Mockito的时候也踩过一模一样的坑!核心原因是Mockito模拟出来的对象,每个方法都是独立的,不会自动继承真实类里的方法调用逻辑。

你存根了isPermitted("review:edit:regional")返回false,但这只对直接调用isPermitted有效。而checkPermission方法在模拟的Subject里,默认是啥都不做的空实现——它不会像真实的Shiro Subject那样,内部调用isPermitted并在返回false时抛出AuthorizationException。

两种可行的解决方案:

方案1:直接存根checkPermission方法抛出异常

既然你的测试场景是要验证调用checkPermission("review:edit:regional")时会触发权限异常,最直接的方式就是直接给这个方法的调用存根抛出异常:

// 注意这里要用doThrow语法,因为checkPermission是void方法
doThrow(new AuthorizationException())
    .when(subject)
    .checkPermission("review:edit:regional");

这样当你的静态类调用subject.checkPermission("review:edit:regional")时,就会抛出预期的异常,测试就能正常通过了。

方案2:让checkPermission关联isPermitted的存根逻辑

如果你希望模拟更贴近真实Subject的行为(比如所有权限校验都遵循isPermitted的结果),可以用thenAnswer来让checkPermission方法根据isPermitted的返回值决定是否抛异常:

// 先存根isPermitted的逻辑
when(subject.isPermitted("review:edit:regional")).thenReturn(false);
// 再让checkPermission调用isPermitted并处理结果
when(subject.checkPermission(anyString())).thenAnswer(invocation -> {
    String permission = invocation.getArgument(0);
    if (!subject.isPermitted(permission)) {
        throw new AuthorizationException("权限不足");
    }
    return null; // checkPermission是void方法,返回null即可
});

这种方式适合需要批量处理多个权限校验场景的测试,不用逐个存根checkPermission。

补充说明

你测试isPermitted时符合预期,是因为你直接给这个方法设置了返回值,Mockito会严格按照你存根的逻辑返回。而checkPermission作为void方法,Mockito默认不会执行任何操作,也不会自动关联其他方法的存根,所以才会出现你看到的现象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:41:50