Skip to content


Mocking static java.util.Logger with EasyMock’s PowerMock extension

We have a class that needs to limit the number of logged messages to avoid DDOSes. But this particular piece of software is still using JULI (yes, I know, not my decision though). Since JULI doesn’t support NDC or MDC, we needed to get creative to test this logging limit.

You probably create a static logger for your class, something like

public class LoggingClass {
    private static Logger logger = Logger.getLogger(LoggingClass.class.getName());
    ...
}

or the equivalent with SLF4J’s LoggerFactory.

PowerMock can help you mock this logger. Yes, its that powerful. First, add it as a Maven dependency (shocker). Your pom.xml might look something like this:

    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-module-junit4</artifactId>
      <version>1.4.8</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-api-easymock</artifactId>
      <version>1.4.8</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.easymock</groupId>
      <artifactId>easymock</artifactId>
      <version>3.0</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>

Now, in order to mock this Logger, we must suppress static initialization for the LoggingClass and then set the value of this static field using the PowerMock API.

import java.util.logging.Logger;
 
import org.junit.Before;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
 
@RunWith(PowerMockRunner.class)
@SuppressStaticInitializationFor("com.example.LoggingClass")
@PrepareForTest({LoggingClass.class})
public class LoggingClassTest extends EasyMockSupport {
 
    private Logger logger;
 
    @Before public void setUp () {
        logger = createMock(Logger.class);
        Whitebox.setInternalState(LoggingClass.class, logger);
    }
 
    ...
}

Now you just use logger like any other mock.

This approach should work for mocking other logging frameworks as well, but YMMV. You’ll need to make some PowerMock API changes since you’d be mocking a non-system class (any other 3rd party logging library). This could be as simple as using something like @PrepareForTest(LoggerFactory.class) in place of the one above (for SLF4J’s LoggerFactory). Or it might be much more difficult. I haven’t tried it.

Posted in Tutorials.


0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.



Some HTML is OK

or, reply to this post via trackback.

 



Log in here!