Mockito Programming Model: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 112: Line 112:


==<span id='Argument_Matcher'></span>Argument Matchers==
==<span id='Argument_Matcher'></span>Argument Matchers==
The [[Software_Testing_Concepts#Test_Double|test double]] can be configured prior to running the test and programmed how to react when a specific method is invoked with various arguments. This is achieved using a mechanism called '''argument matchers'''.
===<tt>isA()</tt>===
===<tt>isA()</tt>===
<syntaxhighlight lang='java'>
<syntaxhighlight lang='java'>

Revision as of 18:03, 16 July 2021

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 void method invoked on it will just work. 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).<voidmethod>(arguments);
doThrow(IOException.class).when(mockExternalDependency).writeLine("....");

Stub Responses for Non-Void Methods

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 specific method is invoked with various arguments. This is achieved using a mechanism called argument matchers.



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?

anyString()