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.
0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.