So, in case you haven’t read the first part in this series, which is giving some basic introduction to the idea of JUnit testing – go ahead, I’ll wait till you’re back so that we can proceed with the next steps.

Yes, I’ve got the basics, go on, I hear you say. 

Great. Let’s now proceed with getting testing support. Let’s say our System Under Test (SUT) has some collaborator objects, which is most often the case, and we want to configure behaviour of these objects in our SUT tests. In this case, we’ll use Mockito library.

In real life, a developer with a SUT depends on other collaborators to help complete this responsibility. It might be that we’re about to build an app that streams music, and we’re creating UserService to list favourite playlists for current user. Or, it may be that we’ll make UserService dependant on a  PlaylistService which is capable of returning playlists for particular user. In such an instance, in order to test our UserService in isolation, we’ll have to configure our collaborator – PlaylistService in terms of behaviour so that we can test our UserService.

During application runtime, in various situations, our collaborators might return some values. Alternatively, sometimes they return empty collections, or might throw an exception. The idea is that we’d like to mimic these kind of situations in our tests, so that we confirm our SUT works as planned for different collaborators behaviours. 

OK… How do I get Mockito? Hope I don’t need bunch of JARs downloaded and configured just to get started.

No, not at all. We’ll continue coding from where we left off after completing the first part. We’ll use Maven to help us do dependency setup, so we’ll open our pom.xml and insert our dependency:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.10.19</version>
    <scope>test</scope>
</dependency>

All we have to do is insert this snippet inside the <dependencies> tag of our pom.xmlMaven will get mockito-core-1.10.19.jar downloaded for us and ready to use in our tests.

 Can I see Mockito in action? You can explain the details to me on the fly…

Sure. Once we’ve done the dependency setup, we can create a simple test case to show the first basic steps. Let’s create MockListTest.java

package com.mydomain.mock_list;

import org.junit.Before;
import org.junit.Test;
import org.mockito.BDDMockito;
import org.mockito.Mock;
import org.mockito.MockingDetails;
import org.mockito.MockitoAnnotations;

import java.util.List;

import static org.junit.Assert.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

public class MockListTest {

@Mock
List&amp;lt;Integer&amp;gt; integerList;

@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}

@Test
public void mockListWithoutAnnotations() throws Exception {
/* given */
final List mockedList = mock(List.class);

given(mockedList.get(3)).willReturn(3);
given(mockedList.size()).willReturn(1);

mockedList.add(2);
mockedList.add(3);
mockedList.add(4);
mockedList.add(5);

/* when */
final int listSize = mockedList.size();

/* then */

final MockingDetails mockingDetails = BDDMockito.mockingDetails(mockedList);
assertTrue(mockingDetails.getInvocations().size() == 5);
assertTrue(listSize == 1);
}

@Test
public void useInjectedMock() throws Exception {
given(integerList.size()).willReturn(1, 2, 3);
integerList.add(3);
assertTrue(integerList.size() == 1);
integerList.add(4);
assertTrue(integerList.size() == 2);
integerList.add(5);
assertTrue(integerList.size() == 3);
}
}

Let’s begin by analysing mockListWithoutAnnotations() test method. We’ve statically imported several Mockito methods to the imports area, such as Mockito.mockBDDMockito.given, so that our code is more readable. The first usage of Mockito API is a call to mock() method, which creates mocked instance of given interface / class.

    Mocked instance?

Yes. In real life we mock our collaborator objects. Here we just mocked an instance of List interface. We use mocking to setup some behaviour of collaborators, and we want to check how our SUT behaves in such a case.

Tests given above are not realistic since they don’t test any SUThere we’re just creating demo how to use APIsMock method receives Class parameter, which is the type we want to mock.

Another way is to use @Mock Mockito annotation. We can just have a class field annotated with annotation and some additional plumbing:

  • We should call MockitoAnnotations.initMocks(this) inside @Before annotated setup method (it’s called by framework once before every test method is executed).
  • We can annotate Test class with @RunWith(MockitoJUnitRunner.class).

    What happens if we don’t configure mocked object and it’s methods get called?

Non void methods return by default an “empty” value appropriate for its type (null, 0, false, empty collection).

    You said we can configure behaviour of collaborator objects… How?

There’s a sequence called Arrange – Act – Assert (AAA) which is to be followed in JUnit tests implementation. In Arrange phase we create mock instances, and configure their behavior. After that, in Act phase, we call SUT method we want tested. Finally, in Assert phase, we assert various condictions to check if SUT executed as expected in given context.

There’s another way to express your tests, which is part of Behavior Driven Developmentwhich states test steps as Given – When – Then (GWT)

BDDMockito.given(mockedList.get(3)).willReturn(3) is an example of stubbing mocks for expected behavior using GWT. Pretty self explanatory – we configure mock to return value 3 when mocked List instance is asked to return value at the index of 3.

BDDMockito.given returns as a result instance of BDDMyOngoingStubbingwhich has the following API  to use when stubbing mocks in our tests:

willAnswer, will, willReturn, willThrow, willCallRealMethod

Most often you’ll probably use willReturn and willThrow when stubbing your collaborators.

Using AAA style, we can configure the same stubbing as GWT using Mockito.when(mockedList.get(2)).thenReturn(2) syntax. We will not cover the differences between AAA and GWT styles. I use GWT style but you can use the one you feel comfortable with.

 What about argument matching?

Mockito, by default, uses equals() for arguments matching. Let’s see it in action: 

@Test
public void testArguments() throws Exception {
final String someString = "some string";
final String notMe = "not me";
final List&amp;lt;String&amp;gt; mockedList = (List&amp;lt;String&amp;gt;) mock(List.class);

given(mockedList.add(someString)).willReturn(true);
given(mockedList.add(Matchers.startsWith("can't add"))).willReturn(false);
given(mockedList.add(Matchers.eq(notMe))).willReturn(false);

assertTrue(mockedList.add(someString));
assertFalse(mockedList.add("can't add 1"));
assertFalse(mockedList.add("can't add 2"));
}

Matchers and AdditionalMatchers APIs provide large set of useful matchers we can use. We have fine grained control of configuring mocks using these. Given above, we’re using Matchers.startsWith and Matchers.eq. So, we can configure mocks to return specific value for exact value of argument it receives, or some other value if argument is / isn’t null, or in case of String we can configure behavior depending on if argument starts with some sequence, ends with, and so forth. Quite often you may find useful family of any() methods, so you can use it to mock methods of particular type, so if mock method receives int you can mock it using Matchers.anyInt() matcher.

What about stubbing void methods?

Let’s do it with an example:

@Test
public void testArguments() throws Exception {
    final String someString = "some string";
    final String notMe = "not me";
    final List<String> mockedList = (List<String>) mock(List.class);

    given(mockedList.add(someString)).willReturn(true);
    given(mockedList.add(Matchers.startsWith("can'twillReturn(false);
    given(mockedList.add(Matchers.eq(notMe))).willReturn(false);

    assertTrue(mockedList.add(someString));
    assertFalse(mockedList.add("can't;
    assertFalse(mockedList.add("can't;
}

List.clear() is a void method, and we can configure void methods to either do nothing (which is default, so we don’t need to configure this) or to throw an exception, as shown in the snippet above.

    And how do I verify if mocked collaborators were actually called?

For such a purpose we can call Mockito.verify API. Verification example:

@Test
public void verificationExample() throws Exception {
final Calculator calculator = mock(Calculator.class);
verify(calculator, Mockito.never()).add(anyLong(), anyLong());
calculator.divide(2, 5);
verify(calculator, times(1)).divide(2, 5);
verify(calculator, atMost(0)).multiply(anyLong(), anyLong());
verify(calculator, never()).add(anyLong(), anyLong());
Mockito.verifyZeroInteractions(calculator);
}

verify has a following signature: Mockito.verify(Mock mock,VerificationMode mode). It receives VerificationMode as second parameter, and Mockito class has some built-in verification modes at your disposal: times(int), atMost(int), never() and so on. The given example above should be pretty self-explanatory. Feel free to explore all verification modes and how to use them by reading Mockito Javadoc. Mockito class also contains verifyZeroInteractions static method that receives varargs of mocks, and returns true if there were no interactions with given mocks, false otherwise.

    Can I capture actual value passed to mock, in order to make some asserts on it?

Great question! Mockito has ArgumentCaptor<T> class that is to be used in such a case. Let’s show how to do that  with simple example. Say we have a class:

package com.mydomain.sut_and_collaborator;

public class MySystemUnderTest {
private Collaborator collaborator;

public MySystemUnderTest(Collaborator collaborator) {
this.collaborator = collaborator;
}

public boolean doSomeStuff(String withArgument) {
return collaborator.doStuff(withArgument);
}
}

Our Collaborator looks like:

package com.mydomain.sut_and_collaborator;

public class Collaborator {
public boolean doStuff(String withArgument) {
return withArgument.contains("some-thing");
}
}

Finally, we’re testing our system under test:

@Test
public void argumentCaptor() throws Exception {
final Collaborator collaborator = mock(Collaborator.class);
ArgumentCaptor&amp;lt;String&amp;gt; captor = ArgumentCaptor.forClass(String.class);
final boolean result = new MySystemUnderTest(collaborator).doSomeStuff("my param");
verify(collaborator).doStuff(captor.capture());
assertTrue(captor.getValue().equals("my param"));
assertFalse(result);
}

We’re calling doSomeStuff on MySystemUnderTest class. All it does is delegate a call to Collaborator class. We want to assert that collaborator object received expected value as an argument. In order to capture value that collaborator received, we need to create ArgumentCaptor<T>, where is type of argument method of collaborator object receives. In our case what gets executed is collaborator.doStuff(String arg). So, we need argument captor of String type. So, in order to capture value passed to collaborator during SUT method test, we need to:

  • Create ArgumentCaptor<T> instance
  • Execute method call on SUT (that calls our collaborator method)
  • Verify collaborator method is executed passing captor.capture() as a method argument
  • Call captor.getValue() to obtain captured value.

ArgumentCaptor<T> also has getAllValues() : List<T> method, which either returns all values if collaborator method receives varargs, or, if method was called multiple times, a list containing these values. Feel free to experiment with captor to get used to the technique for capturing mock method arguments. The argument captor can be created at a test class field level by just putting @Captor annotation (note that the same configuration is required as for @Mock usage – described above) on the field itself, e.g:

@Captor
ArgumentCaptor<String> captor;

    Can I somehow stub real objects behaviour, not only mocked ones?

Yes, Mockito provides support for that. Usually, you don’t want to mock real objects, but in case you need this, say if Mockito has Mockito.spy API, as well as @Spy annotation, the basic idea is that we need to create a spy (proxy object) that will delegate all calls to real object, unless we say we want to override behavior of real object method(s). For example:

@Test
public void spyExample() throws Exception {
final MySystemUnderTest realSUT = new MySystemUnderTest(new Collaborator());
final MySystemUnderTest spySUT = Mockito.spy(realSUT);
final String argument = "Argument";
doReturn(false).when(spySUT).doSomeStuff(argument);
final boolean result = spySUT.doSomeStuff(argument);
assertFalse(result);
}

An example of using Spy annotation (note that the same configuration is required as for @Mock usage – described above) is having a field of our Test case declared such as:

@Spy
MySystemUnderTest systemUnderTest = new MySystemUnderTest(new Collaborator());

If we want to stub behavior of particular SUT spy, we need to use either of doXXX or willXXX methods family. In our case we called:

doReturn(false).when(spySUT).doSomeStuff(argument);

Using Behavior Driven style, we’d accomplish the same using:

willReturn(false).given(spySUT).doSomeStuff(argument);

This way, in case we really need this feature, we can override method behaviour of real object.

    Are there any limitations when using Mockito?

Yes. Although there are hacks how to make workarounds (which might lead to tests hard to understand / maintain), Mockito can’t:

  • Mock final classes and enums
  • Mock final / static / private methods

Key takeaways

  • Mockito is a helper library tailored to perfectly fit JUnit tests development
  • It provides us facilities to configure behavior of our SUT’s collaborator(s)
  • With quite a lightweight syntax, it’s pretty easy to use and configure for your own needs
  • The basic idea is to mock collaborator objects for a specific behavior and after that test our SUT for given collaborator behavior

Source code

Stay tuned and please – don’t forget to subscribe if you’re eager to find out what’s coming next in upcoming posts.

Blog source

JUnit testing – Part II – Using Mockito for Dependency Configuration

| Java Language| 651 views | 1 Comment
Profile photo of Dusan Odalovic
About The Author
-

1 Comment

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>