mergoth mergoth - 23 days ago 9
Java Question

Mocking and verifying SLF4J with JMockit

I have a class with SLF4J logger instanced like:

public class MyClass {

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

public void foo() {
log.warn("My warn");
}
}


And I need to test it with JMockit like:

@Test
public void shouldLogWarn(@Mocked Logger log) throws Exception {
new Expectations() {{
log.warn(anyString);
}};
MyClass my = new MyClass();
my.foo();
}


After searching a lot I figured out, I need to use MockUp somehow. But can't get it how exactly.

Btw, I'm using last version of JMockit(1.29) where you no more can setField(log) for final static fields.

Answer

JMockit has the @Capturing annotation that works for this situation.

Indicates a mock field or a mock parameter for which all classes extending/implementing the mocked type will also get mocked.

Future instances of a capturing mocked type (ie, instances created sometime later during the test) will become associated with the mock field/parameter. When recording or verifying expectations on the mock field/parameter, these associated instances are regarded as equivalent to the original mocked instance created for the mock field/parameter.

This means that if you annotate it with @Capturing instead of @Mocked, every Logger that is created during the test run will be associated with one you annotated. So the following works:

 @Test
 public void shouldLogWarn(@Capturing final Logger log) throws Exception {
   // This really ought to be a Verifications block instead
   new Expectations() {{
     log.warn(anyString);
   }};
   MyClass my = new MyClass();
   my.foo(); 
 }

As a side note, if all you want to do is verify that a method is called, it's better to use Verifications instead, since that is what it is intended for. So your code would look like this:

 @Test
 public void shouldLogWarn(@Capturing final Logger log) throws Exception {
   MyClass my = new MyClass();
   my.foo(); 
   new Verifications() {{
     log.warn(anyString);
   }};
 }