如何模拟 Authentication.getAuthorities()

问题描述 投票:0回答:1

我有一个 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个回答
0
投票

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

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

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

但更可持续的解决方案是首先不要模拟

Authentication
接口,而是使用专门实现来支持测试的实现:
TestingAuthenticationToken
:

final Authentication authentication = new TestingAuthenticationToken(
  null, // principal
  null, // credentials
  "MyRole"); // authority roles
© www.soinside.com 2019 - 2024. All rights reserved.