Tuesday 18 March 2014

Mockito for Testing


A unit test should test a class in isolation. Side effects from other classes or the system should be eliminated if possible. The achievement of this desired goal is typical complicated by the fact that Java classes usually depend on other classes. To solve this, you can use stubs or mock objects.

Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with clean & simple API. Mockito doesn't give you hangover because the tests are very readable and they produce clean verification errors.

Mockito supports the creation of mock objects with the static mock() method call. It also supports the creation of mock objects based on the @Mock annotation. If you use annotations, you must initialize this mock objects with a MockitoAnnotations.initMocks(this) method call.

Limitations

Mockito has certain limitations. It can not test the following constructs:

  • final classes
  • anonymous classes
  • primitive types

Java Dependecies

Mockito-all is a single jar will all dependencies inlined inside (that is: hamcrest and objenesis libs as of june'11). Mockito-core is just the mockito jar.
Use mockito-core if you want to pull a specific version of hamcrest or objenesis. Mockito-core gives finer control on what jars end up on your classpath. Since maven deals with transitive dependencies well maven users can use mockito-core without any extra hassle

mockito-core

  <!-- needs extra dependencies: objenesis & hamcrest -->
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>1.9.5</version>
  <scope>test</scope>

mockito-all

  <groupId>org.mockito</groupId>
  <artifactId>mockito-all</artifactId>
  <version>1.9.5</version>
  <scope>test</scope>

How to Use Mockito

@Test
public void test1()  {
  MyClass test = Mockito.mock(MyClass.class);
  // define return value for method getUniqueId()
  test.when(test.getUniqueId()).thenReturn(43);
  
  // TODO use mock in test.... 
  
  // now check if method testing was called with the parameter 12 
  Mockito.verify(test).testing(Matchers.eq(12));
  
  // was the method called twice?
  Mockito.verify(test, Mockito.times(2));
  
};

Verify the calls on the mock objects

Mockito keeps track of all the method calls and their parameters to the mock object. You can use the verify() method on the mock object to verify that the specified conditions are met, i.e., that a method has been called with certain parameters.

Mockito Annotations

You also have the @InjectMocks annotation which tries to do constructor dependency injection based on the type. For instance look at the following code:

public class ArticleManagerTest  {

       @Mock private ArticleCalculator calculator;
       @Mock private ArticleDatabase database;
       @Spy private UserProvider userProvider = new ConsumerUserProvider();

       // creates instance of ArticleManager
       // and performs constructor injection on it
       @InjectMocks private ArticleManager manager = new ArticleManager();

       @Test public void shouldDoSomething() {
         MockitoAnnotations.initMocks(this);
           verify(database).addListener(any(ArticleListener.class));
       }
}