Mockito Programming Model: Difference between revisions
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
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?