Mockito Programming Model

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

Internal

Overview

API

import static org.mockito.Mockito.mock;
import com.example.ExternalDependency;

public class SomeClassTest {

  private ExternalDependency mockExternalDependency;

  @Before
  public void setUp() {
    mockExternalDependency = mock(ExternalDependency.class);
  }

  @Test
  public void someTest() throws Exception {
    ...
  }
}

Annotations

import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.example.ExternalDependency;
import static org.mockito.Mockito.when;

public class SomeClassTest {

  private AutoCloseable mocks;

  @Mock
  private ExternalDependency mockExternalDependency;

  @Before
  public void openMocks() {
    mocks = MockitoAnnotations.openMocks(this);
  }

  @After
  public void releaseMocks() throws Exception {
    mocks.close();
  }

  @Test
  public void someTest() throws Exception {
    when(mockExternalDependency.someMethod()).thenReturn(...);
    ...
  }
}

Implementing Stub Functionality

https://github.com/ovidiuf/playground/tree/master/java/mockito/annotation-stub

A stub returns synthetic responses or throws exceptions when its methods are invoked. Mockito supports stubbing and by returning a given value when a specific method of the managed test double is called. Mockito implements the stub functionality with Mockito.when(<method>).thenReturn(...) pattern:

public class ExternalDependency {
  public String someMethod() {
    ...
  }
}
import static org.mockito.Mockito.when;
public class SomeClassTest {

  @Mock
  private ExternalDependency mockExternalDependency;

  @Test
  public void someTest() throws Exception {
    when(mockExternalDependency.someMethod()).thenReturn("some synthetic result");
    ...
  }
}

The when() configures the method(s) to stub, or the trigger action. The then*() methods specify what to do when the trigger is activated. Void methods are a special case.

Void Methods

By default, the managed test double does nothing on void methods, so there's no need to configure anything on it. The invocation on a void method will just complete successfully. If we need to simulate an exception that is thrown by a void method, use this pattern:

Throwing Exceptions for Void Methods

doThrow(exception).when(mock).<void-method-name>(arguments);
doThrow(IOException.class).when(mockExternalDependency).writeLine("....");

Stub Responses for Non-Void Methods

The common pattern on non-void methods is:

when(mockExternalDependency.<some-method>(...)).then*(...);

thenReturn()

thenReturn(...) returns the given value. It has several variants:

  • thenReturn(value): return the same value every time.
  • thenReturn(value1, value2, value3, ...): return the first value on first invocation, second value on the second invocation, etc. The equivalent is: thenReturn(value1).thenReturn(value2).thenReturn(value3). ...

thenThrow()

thenThrow(Throwable) throws the given exception. This can be used together with JUnit feature that provides syntactic support for tests that are supposed to check exceptions (@Test(expected = <exception-class>)).

when(mockExternalDependency.someMethod()).thenThrow(IOException.class);

There is alternative syntax for throwing exceptions on void methods.

thenAnswer()

thenAnswer(Answer answer) executes custom logic and compute a value to return. This turns the stub object into a fake.

thenCallRealMethod()

thenCallRealMethod() delegates the invocation to the real external dependency.

Argument Matchers

The test double can be configured prior to running the test and programmed how to react when a method is invoked with specific arguments by using the Mockito.when(...) API. This is achieved using a mechanism called argument matchers. Argument matchers are used to simulate different responses, either specific return values or exceptions, from a method, depending on the values of the arguments.

The default behavior in absence of any configured argument matcher is that the method returns the default value for the return type: 0 for int, null for String, etc.

The test double can be configured to issue specific responses to a method invocation based on individual argument values, predefined wildcard matchers or custom matchers. When using matchers, all arguments of a method must be provided by matchers. Mixing individual argument values and wildcard matchers is not allowed. The following invocation will fail:

verify(mock).someMethod(1, anyString(), "some string");

However, this situation can be easily worked around by using the eq() in lieu of an individual value:

verify(mock).someMethod(eq(1), anyString(), eq("some string"));

Individual Argument Values

eq()

Wildcard Matchers

Mockito wildcard marchers are static methods of the org.mockito.ArgumentMatchers class.

Matcher Notes
any()
anyObject()
any(Class<T> type)
isA(Class<T> type)
anyVararg()
anyBoolean() anyByte() anyChar() anyInt() anyLong() anyFloat() anyDouble() anyShort() anyString()
anyList() anyListOf(Class<T> c)
anySet() anySetOf(Class<T> c)
anyMap() anyMapOf(Class<K> keyC, Class<V> valueC)
anyCollection() anyCollectionOf(Class<T> c)
anyIterable() anyIterableOf(Class<T> c)
eq(boolean value) eq(byte value) eq(char value) eq(double value) eq(float value) eq(int value) eq(long value) eq(short value) eq(T value)
refEq(T value, String... excludeFields)
same(T value)
isNull() isNull(Class<T> c) notNull() notNull(Class<T> c) isNotNull() isNotNull(Class<T> c)
nullable(Class<T> c)
contains(String substring)
matches(String regex) matches(String regex)
endsWith(String suffix) startsWith(String prefix)
argThat(ArgumentMatcher<T> m) charThat(ArgumentMatcher<Character> m)
booleanThat(ArgumentMatcher<Boolean> m) byteThat(ArgumentMatcher<Byte> m)
shortThat(ArgumentMatcher<Short> m) intThat(ArgumentMatcher<Integer> m)
longThat(ArgumentMatcher<Long> m) floatThat(ArgumentMatcher<Float> m)
doubleThat(ArgumentMatcher<Double> m)

isA()

public class ExternalDependency {
  public String someMethodWithArg(String s) {
    ...
  }
}
import static org.mockito.ArgumentMatchers.isA;
  ...
  Mockito.when(mockExternalDependency.someMethodWithArg(isA(String.class))).thenReturn(...);
}

Why is isA() needed, why not provide the class, directly?

Custom ArgumentMatcher

TODO. "Working with a custom ArgumentMatcher class" section in Mockito Essentials.

Hamcrest