Posts Tagged ‘Agile methods’
Certified Scrum Master!
From now and then, I am certified Scrum Master.
I attended the training lead by Jeff Sutherland (co-founder of Scrum method, CEO of Scrum Inc.).
Jeff gathers both practical knowledge from his personnal experience, and a deep work of research and reflexion on IT and processes around IT. As s skilled manager, engineer and orator, his training brings a lot of information and added value. Many thanks to him!
I’d like to thank Xebia France for their welcome, and, of course, Sungard Global Services and the BKN “Lean and Agile” for investing in its architects continuous improvement.
How to unit test Logger calls?
Case
Sometimes, you need test the Log4J’s loggers are called with the right parameters. How to perform these tests from with JUnit?
Let’s take an example: how to test these simple class and method?
public class ClassWithLogger { private static final Logger LOGGER = Logger.getLogger(ClassWithLogger.class); public void printMessage(Integer foo){ LOGGER.warn("this is the message#" + foo); } }
Example
Define an almost empty Log4J appender, such as:
public class TestAimedAppender extends ArrayList<String> implements Appender { private final Class clazz; public TestAimedAppender(Class clazz) { super(); this.clazz = clazz; } @Override public void addFilter(Filter newFilter) { } @Override public Filter getFilter() { return null; } @Override public void clearFilters() { } public void close() { } @Override public void doAppend(LoggingEvent event) { add(event.getRenderedMessage()); } @Override public String getName() { return "TestAppender for " + clazz.getSimpleName(); } @Override public void setErrorHandler(ErrorHandler errorHandler) { } @Override public ErrorHandler getErrorHandler() { return null; } @Override public void setLayout(Layout layout) { } @Override public Layout getLayout() { return null; } @Override public void setName(String name) { } public boolean requiresLayout() { return false; } }
Then create a TestCase with two fields:
public class ClassWithLoggerUnitTest { private ClassWithLogger classWithLogger; private TestAimedAppender appender; ... }
In the setup, remove all appenders, create an instance of our appender, and then add it to the logger related to the class which we want to test:
@Before public void setUp() throws Exception { final Logger classWithLoggerLogger = Logger.getLogger(ClassWithLogger.class); classWithLoggerLogger.removeAllAppenders(); appender = new TestAimedAppender(ClassWithLogger.class); classWithLoggerLogger.addAppender(appender); appender.clear(); classWithLogger = new ClassWithLogger(); }
Then write the following test. The code is documented:
@Test public void testPrintMessage() throws Exception { final String expectedMessage = "this is the message#18"; // empty the appender appender.clear(); // check it is actually empty before any call to the tested class assertTrue(appender.isEmpty()); // call to the tested class classWithLogger.printMessage(18); // check the appender is no more empty assertFalse(appender.isEmpty()); assertEquals(1, appender.size()); // check the content of the appender assertEquals(expectedMessage, appender.get(0)); }
Conclusion
This basic example shows how to perform tests on logger, without overriding the original code or using mocks. Of course, you can improve this basic example, for instance in discriminating owing to the log level (INFO
, WARN
, ERROR
, etc.), use generics, and even any other fantasy ;-).