Mock Me With Fewer Words

With Mockito 1.8.3 or higher you can significantly reduce your test code setup.

Here is the code before.

public class MockitoTest {
 
   private EmailFactory emailFactory;
   private Notifier notifier;
   private Emailer emailer;
   private Email email;
 
   @Before
   public void setUp(){
      notifier = new Notifier();
 
      emailFactory = mock(EmailFactory.class);
      emailer = mock(Emailer.class);
      email = mock(Email.class);
 
      notifier.setEmailFactory(emailFactory);
      notifier.setEmailer(emailer);
   }
 
   @Test
   public void testSend(){
      when(emailFactory.create()).thenReturn(email);
 
      notifier.send();
 
      verify(emailFactory).create();
      verify(emailer).send(email);
      verifyNoMoreInteractions(emailFactory);
      verifyNoMoreInteractions(emailer);
   }
}
   public class Notifier{
      private EmailFactory emailFactory;
      private Emailer emailer;
 
      public void send(){
         Email email = emailFactory.create();
         emailer.send(email);
      }
 
      public void setEmailer(Emailer emailer) {
         this.emailer = emailer;
      }
 
      public void setEmailFactory(EmailFactory emailFactory) {
         this.emailFactory = emailFactory;
      }
   }

Here is the code using the new annotations.

@RunWith(MockitoJUnitRunner.class)
public class MockitoAnnotationsTest {
 
   @Mock private EmailFactory emailFactory;
   @Mock private Emailer emailer;
   @Mock private Email email;
   @InjectMocks private Notifier notifier = new Notifier();
 
   @Test
   public void testSend(){
      when(emailFactory.create()).thenReturn(email);
 
      notifier.send();
 
      verify(emailFactory).create();
      verify(emailer).send(email);
      verifyNoMoreInteractions(emailFactory);
      verifyNoMoreInteractions(emailer);
   }
}
   public class Notifier{
      private EmailFactory emailFactory;
      private Emailer emailer;
 
      public void send(){
         Email email = emailFactory.create();
         emailer.send(email);
      }
   }

This new annotation style reduced the number of lines of code by over 40%. The longer a test is the harder it is to understand. Reducing the amount of test code increases its clarity.

So how does it work? ‘@Mock’ is equivalent ‘Mockito.mock(Some.class)’. ‘@InjectMocks’ is equivalent to setting the mocks on the class under test. This annotation uses reflection to set properties so you do not have to add setters just for testing. Lastly, the combination of ‘@RunWith(MockitoJUnitRunner.class)’ and ‘@InjectMocks’ enables you to remove the ‘@Before’ method. This pair of annotations prepares the class under test before each test method.

I have been using mocks in tests for years and this is a great addition to this powerful framework.

One comment

Comments are closed.