log4j testing

140 views
Skip to first unread message

CowOfDoom

unread,
Dec 8, 2008, 9:25:09 PM12/8/08
to testng-users
Hi all,

I've got several classes in an application wired together with
Spring. I do my testing with TestNG, which is especially easy because
my ability to wire things up as needed, occasionally to mock objects.

However, for one class, I want to be able to assert that a very
important log message is output via log4j, and output with the correct
level of importance (FATAL). Google has failed to provide me with an
obvious solution, and so I ask how you guys might handle this.

Most of my classes that use the log have a line like this near the
top:

private static final Logger log = Logger.getLogger(ThisClass.class);

With this style, I do not believe there's a clean way to mock out the
logger. I considered making the variable non-static and adding a
setLog() method that would only be used by the test code, but I hate
adding even a single setter to my code if the only place it will be
used is in the tester.

I considered forcing a flush in the log file and examining it in the
test code, but that seemed equally messy.

I also considered writing a custom log4j appender and querying it for
how it's being used, but that seemed like an awful lot of work to test
one small log statement.

Does anyone know of an existing log4j unit testing framework or
technique that solves this problem?

Mark Derricutt

unread,
Dec 8, 2008, 9:51:01 PM12/8/08
to testng...@googlegroups.com
I've not tried this, but I've tried a similar approach:

- Write your own in-memory appender that gives you an ability to check the formatted/printed log output
- Configured log4j to use that appender
- Update your tests to inspect activity on the appender

I guess you could write your test along the lines of:

{
  AssertableAppender.getInstance().startWatchingThoseLogs();
  .... // do something here
  AssertableAppender.getInstance().assertThatStringWasLogged("FATAL Some Error Occured");
}

I think you can add/remove appenders on the fly, so you might even be able to add a mocked appender as opposed to adding a custom one.
--
"It is easier to optimize correct code than to correct optimized code." -- Bill Harlan

thierry.henrio

unread,
Dec 9, 2008, 5:21:07 PM12/9/08
to testng-users
Hi all, testing logging looks like a strange requirement to me :
shouldn't logging be a separated concern from production code ?

Now I must admit to have tested some logging, and testing log4j with
static logger instance is a pain :)
I followed same path as Mark, as I failed to find testing artifact for
this purpose :(

1- have a spy
S1- have a concrete spy appender, S2- have a testing log4j
configuration resource, S3- have context use this log file and S4-
assertThat captured output is as specified
This is "cumbersome", isn't it ?

straightforward S1 was always sufficient for me, something like

public class Log4jCapturingAppender extends AppenderSkeleton {
private Object capture; // + have get to implement spy
@Override
protected void append(LoggingEvent event) {
setCapture(event.getMessage());
}
// + empty required method
}

why was it sufficient ?
may be because you can just execute just enough production code to
produce the logging call you want to spy ...

i found difficult to have an appender defined in a spring xml
resource, and have log4j take advantage of it, has both container are
unrelated
so i followed this "cumbersome" path, and yes it is a pain

Now, may be groovy could help, as it has some bytecode manipulation
capability, but I did not tried yet
I have a groovy task in my private backlog, but this one looks easy to
try, so I shall give it a first go :)

One last thing, isn't the instruction following your FATAL statement
a ... System.exit ??

On Dec 9, 3:51 am, "Mark Derricutt" <m...@talios.com> wrote:
> I've not tried this, but I've tried a similar approach:
>
> - Write your own in-memory appender that gives you an ability to check the
>
> {

thierry.henrio

unread,
Dec 9, 2008, 6:42:30 PM12/9/08
to testng-users
Oh I forgot about "powermock" that has capability to test static
method
it might suit you, if you like easymock record/replay style
Reply all
Reply to author
Forward
0 new messages