SwimsZoots SwimsZoots - 1 month ago 11
Java Question

Using JMockit to mock autowired interface implementations

We are writing JUnit tests for a class that uses Spring autowiring to inject a dependency which is some instance of an interface. Since the class under test never explicitly instantiates the dependency or has it passed in a constructor, it appears that JMockit doesn't feel obligated to instantiate it either.

Up until now we have been using SpringRunner to have Spring load mock dependencies for us, which works. Two things we don't like about this are 1) the Spring framework has to be loaded and initialized each time running the tests which is not exactly speedy, and 2) we are forced to explicitly create all mock dependencies as real classes, something which JMockit helps eliminate.

Here's a simplified example of what we're testing:

public class UnitUnderTest {

@Autowired
ISomeInterface someInterface;

public void callInterfaceMethod() {

System.out.println( "UnitUnderTest.callInterfaceMethod calling someInterface.doSomething");
someInterface.doSomething();
}

}


So, the question is, is there a way to have JMockit create a mock
someInterface
?

Answer

JMockit will always instantiate a mocked interface (except in the case of a final mock field), but that only occurs in test code. It will not automatically inject the instance into code under test.

You would have to manually inject the mock instance. For example:

public class SomeTest
{
   @Autowired UnitUnderTest unitUnderTest;
   @Mocked ISomeInterface theMock; // created and assigned automatically

   @Test
   public void testSomeMethod()
   {
      Deencapsulation.setField(unitUnderTest, theMock);
      //proceed with unit test here
   }
}

mockit.Deencapsulation is a Reflection-based utility class that lets you invoke private methods, get/set fields, etc.