Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I test with junit that a warning was logged with log4j? [duplicate]

I'm testing a method that logs warnings when something went wrong and returns null.
something like:

private static final Logger log = Logger.getLogger(Clazz.class.getName()); .... if (file == null || !file.exists()) {   // if File not found   log.warn("File not found: "+file.toString()); } else if (!file.canWrite()) {   // if file is read only   log.warn("File is read-only: "+file.toString()); } else {   // all checks passed, can return an working file.   return file; } return null; 

i'd like to test with junit that a warning was issued, in addition to returning null, in all cases (e.g. file not found, file is read-only).
any ideas?
thanks, asaf :-)


UPDATE

My implementation of Aaron's answer (plus peter's remark):

public class UnitTest { ...  @BeforeClass public static void setUpOnce() {   appenders = new Vector<Appender>(2);   // 1. just a printout appender:   appenders.add(new ConsoleAppender(new PatternLayout("%d [%t] %-5p %c - %m%n")));   // 2. the appender to test against:   writer = new StringWriter();   appenders.add(new WriterAppender(new PatternLayout("%p, %m%n"),writer)); }  @Before public void setUp() {   // Unit Under Test:   unit = new TestUnit();   // setting test appenders:   for (Appender appender : appenders) {     TestUnit.log.addAppender(appender);   }   // saving additivity and turning it off:   additivity = TestUnit.log.getAdditivity();   TestUnit.log.setAdditivity(false); }  @After public void tearDown() {   unit = null;   for (Appender appender : appenders) {     TestUnit.log.removeAppender(appender);   }   TestUnit.log.setAdditivity(additivity); }  @Test public void testGetFile() {   // start fresh:   File file;   writer.getBuffer().setLength(0);    // 1. test null file:   System.out.println(" 1. test null file.");   file = unit.getFile(null);   assertNull(file);   assertTrue(writer.toString(), writer.toString().startsWith("WARN, File not found"));   writer.getBuffer().setLength(0);    // 2. test empty file:   System.out.println(" 2. test empty file.");   file = unit.getFile("");   assertNull(file);   assertTrue(writer.toString(), writer.toString().startsWith("WARN, File not found"));   writer.getBuffer().setLength(0); } 

thanks guys,

like image 310
Asaf Avatar asked Sep 15 '10 12:09

Asaf


People also ask

How do I test a logger message in Junit?

@StefanoL: If a logger is defined with private static final Logger LOGGER = Logger. getLogger(someString); , you can still access it from unit tests with Logger. getLogger(someString); , modify it and add handlers (as in the accepted answer).

How do I cover log debug in Junit?

how to change the log level for certain junit test methods. The way to go is to use a custom junit MethodRule that accesses the loggers and re-configures the log level per package. With below classes, you can achieve this.

Does junit use log4j?

Learn to use a different Log4j2 configuration file for JUnit tests is a recommended approach. We can apply two ways to configure Log4j2 specific to tests and that is different from the production logging config file.

What is LogCaptor?

🎯 LogCaptor captures log entries for unit testing purposes.


2 Answers

In the setup of the unit test:

  1. Get the same logger
  2. Make it non-additive
  3. Add an appender which remembers the messages in a list:

    public class TestAppender extends AppenderSkeleton {     public List<String> messages = new ArrayList<String>();      public void doAppend(LoggingEvent event) {         messages.add( event.getMessage().toString() );     } } 
  4. Add the appender to the logger

Now you can call your code. After the test, you will find all log messages in the list. Add the log level if you want (messages.add( event.getLevel() + " " + event.getMessage() );).

In tearDown(), remove the appender again and enable additivity.

like image 92
Aaron Digulla Avatar answered Sep 24 '22 02:09

Aaron Digulla


Using Mockito you can test the logging that occurred during your test with minimal boiler plate code, a simple example is:

@RunWith(MockitoJUnitRunner.class) public class TestLogging {    @Mock AppenderSkeleton appender;   @Captor ArgumentCaptor<LoggingEvent> logCaptor;     @Test   public void test() {     Logger.getRootLogger().addAppender(appender);      ...<your test code here>...      verify(appender).doAppend(logCaptor.capture());     assertEquals("Warning message should have been logged", "Caution!", logCaptor.getValue().getRenderedMessage());   } } 
like image 35
josle Avatar answered Sep 25 '22 02:09

josle