Tuesday, November 15, 2011

Eclipse: make sure your unit test uses the project's classpath

I was getting this error when trying to run a unit test through Eclipse (Indigo 3.7).

java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.arrayFormat(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
 at ch.qos.logback.classic.spi.LoggingEvent.getFormattedMessage(LoggingEvent.java:282)
   ...

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/MyProject/lib/logback-classic-0.9.15.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/MyProject/lib/logback-classic-0.9.27.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: The requested version 1.5.6 by your slf4j binding is not compatible with [1.6]
SLF4J: See http://www.slf4j.org/codes.html#version_mismatch for further details.

Turns out the key line was SLF4J: Class path contains multiple SLF4J bindings - it was finding StaticLoggerBinder classes in multiple places (specifically logback-classic-0.9.15.jar and logback-classic-0.9.27.jar). In our project, we kept both versions of the jar in our lib directory, but were only referencing the latest one in the .classpath file. Unfortunately, by default, the JUnit Run Configuration ignores your project classpath and instead just scans for jars.

To stop this from happening, go Run > Run Configurations > MyTestName > Classpath tab > User entries > click on myappname (default classpath) > Edit > tick "Only include exported entries" > OK > Apply > Run. Now the unit test's run configuration will use your project's classpath.