Injecting Logs into Seam Beans
When using the Seam container there is a useful @Logging
annotation which injects a Log
object at runtime into the bean. In the seam documentation for unit testing the advice generally is to have setters on the class to allow the dependencies to be set. For logging this is not really desirable. One alternative for this is to write a small class that will inject a Log object prior to testing:
import java.lang.reflect.Field; import org.jboss.seam.annotations.Logger; import org.jboss.seam.log.Log; public class LoggerInjector { public void injectLogger(Object target,Log mockLog) { for ( Field field: target.getClass().getDeclaredFields()) { if (field.getAnnotation(Logger.class)!=null) { field.setAccessible(true); try { field.set(target,mockLog); } catch (IllegalArgumentException e) { throw new AssertionError("Failed injecting logger for test: illegal argument: " + e.getMessage()); } catch (IllegalAccessException e) { throw new AssertionError("Failed to access field to inject logger: " + e.getMessage()); } } } } }
The seam Log
object is a useful at runtime as it removes some of the need to wrap each debug statement in a condition to prevent unnecessary string-concatenation. However to do this java5's varargs are used. This can make setting mocking expectations in frameworks like JMock a little more tricky (not impossible). I tend to produce a dummy object implementing org.jboss.seam.log.Log
that outputs nothing and inject that. So a hypothetical test would be:
public class BeanTest { private SeamBean forTest; @Before public void setUp() { LoggerInjector injector = new LoggerInjector(); this.forTest = new SeamBean(); //DummyLog is my implementation of Log Log dummyLog = new DummyLog(); injector.injectLog(forTest,dummyLog); } @Test public void testSomething() { ... } ... }
A drawback of this approach is, if the the @Logger
annotation is in a superclass the injection mechanism will not work.
Add new comment