调用Spring SecurityContextHolder时出现NullPointerException

时间:2015-03-13 19:20:27

标签: java spring mockito

我一直在尝试为以下代码行编写一个测试用例,但我一直得到java.lang.NullPointerException,我试图跟踪/复制其他人在这里提出的建议Unit testing with Spring Security但我没有运气。有人可以帮我更好地识别或暗示我需要做什么。 (我正在使用mockito)

代码:

if (SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals(user)) {
                continue;
            }

测试用例:

@Test
public void testExpireAllSession() throws Exception {

        SecurityContext securityContext = Mockito.mock(SecurityContext.class);
        Mockito.when(securityContext.getAuthentication().getPrincipal().equals(any(Object.class))).thenReturn(false);
        SecurityContextHolder.setContext(securityContext);

       controller.theMEthodUnderTest();
}

...

2 个答案:

答案 0 :(得分:2)

您的测试有两个问题:

  1. 你必须模仿每个"等级"方法调用,你应该模拟:

    • SecurityContext.getAuthentication()
    • Authentication.getPrincipal()
    • Principal.equals()
  2. ,您无法模拟.equals(),请参阅Mockito FAQ - limitationsMockito - Issue 61

  3. 您必须以不同方式设计代码/测试。例如,传递用户'您的方法参数的主体,并使Authentication.getPrincipal()返回另一个(它们将是不同的,从而使等号返回false):

    <强>代码

    public void theMethod(Principal user) {
      ...
      if (SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals(user)) {
        continue;
      }
      ...
    }
    

    <强>测试

    @Test public void testController() {
        SecurityContext securityContext = Mockito.mock(SecurityContext.class);
        Authentication authentication = Mockito.mock(Authentication.class);
        Principal principal1 = Mockito.mock(Principal.class);
        Principal principal2 = Mockito.mock(Principal.class);
        Mockito.when(authentication.getPrincipal()).thenReturn(principal1);
        Mockito.when(securityContext.getAuthentication()).thenReturn(authentication);
        SecurityContextHolder.setContext(securityContext);
        new Controller().theMethod(principal2);
    }
    

答案 1 :(得分:2)

我做了很多重要的事情来完成这项工作,并希望这也有助于其他人。

  1. 使用@InjectMocks:
     
    @InjectMocks
    private static YourMainController controller;
    
  2. 模拟将添加到上面的主模拟的依赖项:
     
    @Mock SecurityContext securityContextMocked; @Mock Authentication authenticationMocked; @Mock Principal principal1;
  3. 修改测试看起来像这样,这使它很好地工作。
     
    @Test

    public void testExpireAllSession() throws Exception {

    List mySessions = new ArrayList<>();
 
    Object principal="";

    Date aDate = new Date();
 

    SessionInformation sessionInformation = new SessionInformation(principal,”100000”,aDate);
 mySessions.add(sessionInformation);
 allUsers.add("Mike"); when(authenticationMocked.getPrincipal()).thenReturn(principal1);
when(securityContextMocked.getAuthentication()).thenReturn(authenticationMocked); SecurityContextHolder.setContext(securityContextMocked);
when(sessionRegistryMocked.getAllSessions(allUsers,false)).thenReturn(sessions); when(sessionRegistryMocked.getAllPrincipals()).thenReturn(allUsers); controller.expireAllSession(); verify(sessionRegistryMocked).getAllPrincipals();
 
 

    }