Monday, December 1, 2014

How could I unit test on the message came from log4j?

I was ask to unit test every single function that I wrote, and I was so unlucky that every function I wrote do invoke log4j. I was thinking whether I should cover those in my unit test as well? There is not much resources found on Internet, mat be due to the reason this really waste of effort or they are more concern on the logic design than this. But I'm so curious on how the code is if I'm insist to go with it. For the purpose of this, I have create an POC as shown below. Let's assume I'm going to unit test on funcA():
public class EmployeeImpl { 

 private static Logger log; 

 public static void initLog() { 
   
  log = Logger.getLogger(EmployeeImpl.class); 
  log.setLevel(Level.INFO); 
  log.setAdditivity(false); 
   
  ConsoleAppender ca = new ConsoleAppender(); 
  ca.setWriter(new OutputStreamWriter(System.out)); 
  ca.setLayout(new PatternLayout("%-5p [%t]: %m%n")); 
  log.addAppender(ca); 
 } 
  
 public static void funA() { 
  log.info("Entering into funcA"); 
 } 
}

Next I have my unit test as shown below targeting on funcA():
@RunWith(PowerMockRunner.class)
public class EmployeeImplTest { 
  
 @Mock 
 private Appender appenderMock; 
  
 @Captor 
 private ArgumentCaptor<loggingevent> loggingEvent; 

 @Test 
 public void test() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { 
   
  Logger.getRootLogger().addAppender(appenderMock); 
   
  Field log = EmployeeImpl.class.getDeclaredField("log"); 
  log.setAccessible(true); 
  log.set(null, LogManager.getLogger(EmployeeImpl.class)); 
   
  EmployeeImpl.funA(); 
   
  Mockito.verify(appenderMock, Mockito.times(1)).doAppend((LoggingEvent) loggingEvent.capture()); 
  Assert.assertThat(((LoggingEvent) loggingEvent.getValue()).getLevel(), CoreMatchers.is(Level.INFO)); 
  Assert.assertThat(((LoggingEvent) loggingEvent.getAllValues().get(0)).getRenderedMessage(), CoreMatchers.equalTo("Entering into funcA")); 
 } 
}
Tada!! The test case above test 2 things; 1) Ensure the log level is INFO, 2) Ensure the message Entering into funcA. were shown. Either one is incorrect will failed the test case. In this case, the result will be pass.

No comments: