Skip to content
Advertisement

how to mock static class function with inner method in mockito?

I have a class name HibernateSessionManager which have static method

public static HibernateSessionManager current;

I trying to mock

public Mbc_session getMBCSessionByGuid(String sessionGuid) { 
  try { 
    return HibernateSessionManager.current.withSession(hibernateSession -> { 
       return hibernateSession.get(Mbc_session.class, sessionGuid); 
   }); 
} 
catch (Exception e) { 
  logger.error().logFormattedMessage(Constants.MBC_SESSION_GET_ERROR_STRING, 
    e.getMessage()); throw new DAOException(ErrorCode.MBC_1510.getCode(), ErrorCode.MBC_1510.getErrorMessage() + ",Operation: getMBCSessionByGuid"); 
 } 
}

i am using following function in @before

public static void initMocks(Session session) { 
  HibernateSessionManager.current = mock(HibernateSessionManager.class,Mockito.RETURNS_DEEP_STUBS); 
  HibernateTransactionManager.current = mock(HibernateTransactionManager.class,Mockito.RETURNS_DEEP_STUBS); 
  doCallRealMethod().when(HibernateTransactionManager.current).withTransaction(any(), any()); 
  doCallRealMethod().when(HibernateSessionManager.current).withSession(any(Consumer.class)); 
  // Mockito.when(HibernateSessionManager.current.withSession((Consumer<Session>) any(Function.class))).thenCallRealMethod(); 
  
  when(HibernateSessionManager.current.getSession()).thenReturn(session); 
} 

My test case is following

@Test public void test_getMBCSessionByGuid() { 
  Mbc_session mbcSession = new Mbc_session(); 
  String sessionGuid = "session GUID"; 
  when(HibernateSessionManager.current.getSession()).thenReturn(session); 
  // when(sessionFactory.getCurrentSession()).thenReturn(session); 
  when(session.get(Mbc_session.class, sessionGuid)).thenReturn(mbcSession); 
  Mbc_session mbcSession2 = mbc_sessionDao.getMBCSessionByGuid(sessionGuid); 
  assertNull(mbcSession2); 
} 

it passed but coverage is not touching following code

return hibernateSession.get(Mbc_session.class, sessionGuid); 

here is my withSession code

public void withSession(Consumer<Session> task) { 
     Session hibernateSession = getSession(); 
     try { 
        task.accept(hibernateSession); 
      } finally { 
        HibernateSessionManager.current.closeSession(hibernateSession); 
     } 
} 

openSession

public Session getSession() { 
    Session threadCachedSession = threadSession.get(); 
    if (threadCachedSession != null) { 
       if (!threadCachedSession.isOpen()) { throw new 
          IllegalStateException("Session closed outside of 
           HibernateSessionManager."); 
       } 
       return threadCachedSession; 
     } return sessionFactory.openSession(); 

   } 

Advertisement

Answer

Looking at the code and assuming it compiles, I believe the problem is that you have two withSession(...) methods and in the code posted you are trying to mock the wrong one. Here are their signatures:

// You should NOT mock this one
void withSession(Consumer<Session> task) {
  ...
}

// You should mock this one instead
Mbc_session withSession(Function<Session, Mbc_session> task) {
  ...
}

It was easy to guess as the getMBCSessionByGuid method contains the snippet below with the Function<Session, Mbc_session> being passed as an argument to withSession(...) instead of Consumer<Session>:

return HibernateSessionManager.current.withSession(hibernateSession -> { 
   // something is returned which means a Function is passed, not a Consumer
   return hibernateSession.get(Mbc_session.class, sessionGuid); 
}); 

As an easy fix, you can just add the following to the test:

doCallRealMethod().when(HibernateSessionManager.current).withSession(any(Function.class));

and remove the existing mock configuration with a Consumer:

doCallRealMethod().when(HibernateSessionManager.current).withSession(any(Consumer.class));

P.S. Just in case, I can easily reproduce the issue on my machine.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement