如何模拟 Authentication.getAuthorities()

How do I mock Authentication.getAuthorities()

提问人:Niklas 提问时间:10/22/2023 更新时间:10/22/2023 访问量:39

问:

我有一个Spring OncePerRequestFilter过滤器,其中包含doFilterInternal的实现,如下所示:

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException {
        final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null && containsRole(auth, "SpecificRole")) {
            doThingsWithTheRequest(request);
        }
        filterChain.doFilter(request, response);
    }

containsRole 如下所示:

    protected boolean containsRole(final Authentication auth, final String role) {
        for (final GrantedAuthority ga : auth.getAuthorities()) {
            if (ga.getAuthority().equals(role)) {
                return true;
            }
        }
        return false;
    }

对于我的测试,我有一个JUnit测试,我想模拟Authentication.getAuthorities(),以便containsRole将返回true:

    @Test
    public void test() throws ServletException, IOException, CommerceCartRestorationException {

        SecurityContext securityContextMock = mock(SecurityContext.class);
        Authentication authenticationMock = mock(Authentication.class);

        SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("MyRole");
        Collection<SimpleGrantedAuthority> authCollection = Collections.singleton(simpleGrantedAuthority);

        when(authenticationMock.getAuthorities()).thenReturn(authCollection);
        when(securityContextMock.getAuthentication()).thenReturn(authenticationMock);

        SecurityContextHolder.setContext(securityContextMock);
        
        testObj.doFilterInternal(httpServletRequestMock, httpServletResponseMock, filterChainMock);
    }

我收到编译器错误

无法解析方法“thenReturn(Collection)”

在这一行:

when(authenticationMock.getAuthorities()).thenReturn(authCollection);

getAuthorities 返回此

Collection<? extends GrantedAuthority>

SimpleGrantedAuthority 实现 GrantedAuthority 接口

所以问题是我为什么以及如何解决它?

我见过类似的问题,答案是向spring-security-test添加依赖项并使用@WithMockUser但恐怕使用spring-security-test不是一个选项

spring-security mockito junit4

评论

1赞 subasri_ 10/22/2023
您是否也希望通过方法涵盖方法?如果没有,则可以使用对象来控制对象的返回containsRoledoFilterInternalcontainsRoleSpy

答:

1赞 knittl 10/22/2023 #1

Authentication#getAuthorities具有返回类型,这是一个通配符类型。您不知道实际类型是什么,因此不能为其赋值或将其用作其他方法中的参数。Collection<? extends GrantedAuthority>

一个简单的解决方法是强制转换为原始集合类型:

Mockito.when(authenticationMock.getAuthorities())
    .thenReturn((Collection) authorityCollection);

但更可持续的解决方案是首先不要模拟接口,而是使用专门实现来支持测试的实现:TestingAuthenticationTokenAuthentication

final Authentication authentication = new TestingAuthenticationToken(
  null, // principal
  null, // credentials
  "MyRole"); // authority roles