07 November 2012

Disable Logging For unit Test

Step 1: Create a class that will filter certain log messages. This will be your Logger's custom filter. In the example below, it will iterate through all the mFilterMessages and if the error message matches, starts with or ends with one of the strings stored in the mFilterMessages, it will not create a log entry.

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Filter;
import java.util.logging.LogRecord;

public class CustomLogFilter implements Filter {
    private List mFilterMessages;

    public CustomLogFilter(){
        super();
        mFilterMessages = new ArrayList();
    }

    public CustomLogFilter(List filterMessages){
        mFilterMessages = new ArrayList();
        mFilterMessages.addAll(filterMessages);
    }

    @Override
    public boolean isLoggable(LogRecord lr){
        String msg = lr.getMessage();
        if (mFilterMessages.contains(msg))
        {
            return false;
        }
        else
        {
            for (String filterMessage : mFilterMessages)
            {
                if (msg.startsWith(filterMessage))
                {
                    return false;
                }
                else if (msg.endsWith(filterMessage))
                {
                    return false;
                }
                else if (msg.contains(filterMessage))
                {
                    return false;
                }
            }
        }
        return true;
    }
}

Step 2: Create some sort of util class that will easily set/reset your custom filter.

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Filter;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import org.apache.commons.logging.LogFactory;

public class CustomLogDisabler{
    private Logger mLogger;
    private static boolean mIsActive;
    private static Filter mOldLogFilter;
    private List mFilterMessages = new ArrayList();

    public static CustomLogDisabler newInstance(String pDefaultLoggerName) {
        CustomLogDisabler cld = new CustomLogDisabler(pDefaultLoggerName);
        return cld;
    }

    protected CustomLogDisabler() {}

    protected CustomLogDisabler(String pDefaultLoggerName){
        mIsActive = false;
        mLogger = LogManager.getLogManager().getLogger(pDefaultLoggerName);
        if (mLogger == null) {
            LogFactory.getLog(pDefaultLoggerName);
            mLogger = LogManager.getLogManager().getLogger(pDefaultLoggerName);
        }
        mOldLogFilter = mLogger.getFilter();
    }

    public boolean isActivated() {
        if (mIsActive) {
            return true;
        }
        return false;
    }

    public void activate() {
        mIsActive = true;
        Filter newFilter = new CustomLogFilter(mFilterMessages);
        mLogger.setFilter(newFilter);
    }

    public void deactivate() {
        mIsActive = false;
        mOldLogFilter = null;
        mFilterMessages = new ArrayList();
        mLogger.setFilter(mOldLogFilter);
    }

    public void addMessage(String pMessage) {
        mFilterMessages.add(pMessage);
    }
}

Step 3a: In your JUnit test add private field

private CustomLogDisabler mLogDisabler;

Step 3b: In your JUnit @Before method, set mLogDisabler = null

@Before
public void setUp() {
    mLogDisabler = null;
    ...
}

Step 3c: In your JUnit @After method, reset mLogDisabler

@After
public void tearDown(){
    if (mLogDisabler != null){
        mLogDisabler.deactivate();
    }
}

Step 3d: In your @Test method, initialize and activate the mLogDisabler. In this example, what you're testing is the class "YourClassName" which is in package "com.a.b". By adding the "Error reading this" to your mLogDisabler, any log messages that matches, start with or ends with "Error reading this" will not be created.

@Test
public void testRead() {
    mLogDisabler = CustomLogDisabler.newInstance("com.a.b.YourClassName");
    mLogDisabler.addMessage("Error reading this");
    mLogDisabler.activate();

    //your testing goes here
}