views:

636

answers:

3

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?

+3  A: 

You can use org.springframework.test.util.ReflectionTestUtils to explicitly inject your mocked ISomeInterface in your test case.

See documentation

Paul McKenzie
(+1) that's one good class I didn't know of :)
Bozho
I love finding these little gems in the Spring API... +1
skaffman
This is a useful class to be sure. Still, having to explicitly create the mock defeats one of the main reasons for using JMockit in the first place.
SwimsZoots
+3  A: 

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.

Rogerio
Brilliant! If only the jmockit documentation exposed this information a bit more...
Steen
+1  A: 

With the hints kindly provided above, here's what I found most useful as someone pretty new to JMockit: JMockit provides the Deencapsulation class to allow you to set the values of private dependent fields (no need to drag the Spring libraries in), and the MockUp class that allows you to explicitly create an implementation of an interface and mock one or more methods of the interface. Here's how I ended up solving this particular case:

@Before
public void setUp() {

   IMarketMakerDal theMock = new MockUp <IMarketMakerDal>() {

      @Mock
      MarketMakerDcl findByMarketMakerGuid( String marketMakerGuid ) {

         MarketMakerDcl marketMakerDcl = new MarketMakerDcl();
         marketMakerDcl.setBaseCurrencyCode( CURRENCY_CODE_US_DOLLAR );
         return marketMakerDcl;
      }
   }.getMockInstance();

   setField( unitUnderTest, theMock );
}

Thanks everyone for the help.

SwimsZoots