Mockito Annotations and Usage Guide
Mockito Annotations and Usage Guide
2.1. MockitoJUnitRunner 3
2.2. MockitoAnnotations.openMocks() 3
2.3. MockitoJUnit.rule() 3
3. @Mock Annotation 4
4. @Spy Annotation 5
5. @Captor Annotation 7
6. @InjectMocks Annotation 8
9. Notes 11
10. Conclusion 12
2. The Examples 15
3. Conclusion 17
2. Simple Mocking 20
6. Conclusion 25
2. The Examples 28
3. Conclusion 31
5. Mockito ArgumentMatchers
1. Overview 33
2. Maven Dependencies 34
3. ArgumentMatchers 35
6. Conclusion 41
4. Stubbing a Spy 46
7. Conclusion 49
2. Using ArgumentCaptor 52
3. Avoiding Stubbing 55
3.1. Decreased Test Readability 55
4. Conclusion 57
3. Argument Capture 61
5. Partial Mocking 63
6. Conclusion 64
7. Conclusion 65
6. Conclusion 72
10. Mock Final Classes and Methods With Mockito
1. Overview 74
4. Conclusion 77
4. Exception as an Object 82
5. Spy 83
6. Conclusion 84
2. Maven Dependencies 87
3. Mockito Extension 88
1
1. Overview
In this chapter, we’ll cover the following annotations of the Mockito library:
@Mock, @Spy, @Captor, and @InjectMocks.
2
2. Enable Mockito Annotations
Before we get started, let’s explore different ways to enable the use of
annotations with Mockito tests.
2.1. MockitoJUnitRunner
1. @ExtendWith(MockitoExtension.class)
2. public class MockitoAnnotationUnitTest {
3. ...
4. }
2.2. MockitoAnnotations.openMocks()
1. @BeforeEach
2. public void init() {
3. MockitoAnnotations.openMocks(this);
4. }
2.3. MockitoJUnit.rule()
3
3. @Mock Annotation
The most widely used annotation in Mockito is @Mock. We can use @Mock
to create and inject mocked instances without having to call Mockito.mock
manually.
1. @Test
2. public void whenNotUseMockAnnotation_thenCorrect() {
3. List mockList = Mockito.mock(ArrayList.class);
4.
5. mockList.add(“one”);
6. Mockito.verify(mockList).add(“one”);
7. assertEquals(0, mockList.size());
8.
9. Mockito.when(mockList.size()).thenReturn(100);
10. assertEquals(100, mockList.size());
11. }
Now we’ll do the same, but we’ll inject the mock using the
@Mock annotation:
1. @Mock
2. List<String> mockedList;
3.
4. @Test
5. public void whenUseMockAnnotation_thenMockIsInjected() {
6. mockedList.add(“one”);
7. Mockito.verify(mockedList).add(“one”);
8. assertEquals(0, mockedList.size());
9.
10. Mockito.when(mockedList.size()).thenReturn(100);
11. assertEquals(100, mockedList.size());
12. }
Note how in both examples, we’re interacting with the mock and verifying
some of these interactions, just to make sure that the mock is behaving
correctly.
4
4. @Spy Annotation
Now let’s see how to use the @Spy annotation to spy on an existing
instance.
1. @Test
2. public void whenNotUseSpyAnnotation_thenCorrect() {
3. List<String> spyList = Mockito.spy(new ArrayList<String>());
4.
5. spyList.add(“one”);
6. spyList.add(“two”);
7.
8. Mockito.verify(spyList).add(“one”);
9. Mockito.verify(spyList).add(“two”);
10.
11. assertEquals(2, spyList.size());
12.
13. Mockito.doReturn(100).when(spyList).size();
14. assertEquals(100, spyList.size());
15. }
Now we’ll do the same thing, spy on the list, but we’ll use the @Spy
annotation:
1. @Spy
2. List<String> spiedList = new ArrayList<String>();
3.
4. @Test
5. public void whenUseSpyAnnotation_thenSpyIsInjectedCorrectly() {
6. spiedList.add(“one”);
7. spiedList.add(“two”);
8.
9. Mockito.verify(spiedList).add(“one”);
10. Mockito.verify(spiedList).add(“two”);
11.
12. assertEquals(2, spiedList.size());
13.
14. Mockito.doReturn(100).when(spiedList).size();
15. assertEquals(100, spiedList.size());
16. }
5
Note how, as before, we’re interacting with the spy here to make sure that
it behaves correctly. In this example we:
6
5. @Captor Annotation
1. @Test
2. public void whenNotUseCaptorAnnotation_thenCorrect() {
3. List mockList = Mockito.mock(List.class);
4. ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.
5. class);
6.
7. mockList.add(“one”);
8. Mockito.verify(mockList).add(arg.capture());
9.
10.
11. assertEquals(“one”, arg.getValue());
12. }
Now let’s make use of @Captor for the same purpose, to create an
ArgumentCaptor instance:
1. @Mock
@Test
2. public
List mockedList;
void whenNotUseCaptorAnnotation_thenCorrect() {
3. List mockList = Mockito.mock(List.class);
4. @Captor
ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.
5. class);
ArgumentCaptor argCaptor;
6.
7. @Test
mockList.add(“one”);
8. public
Mockito.verify(mockList).add(arg.capture());
void whenUseCaptorAnnotation_thenTheSame() {
9. mockedList.add(“one”);
10. Mockito.verify(mockedList).add(argCaptor.capture());
11. assertEquals(“one”, arg.getValue());
12. } assertEquals(“one”, argCaptor.getValue());
13. }
Notice how the test becomes simpler and more readable when we take
out the configuration logic.
7
6. @InjectMocks Annotation
Now let’s discuss how to use the @InjectMocks annotation to inject mock
fields into the tested object automatically.
1. @Mock
@Test
2. public void String>
Map<String, whenNotUseCaptorAnnotation_thenCorrect()
wordMap; {
3. List mockList = Mockito.mock(List.class);
4. @InjectMocks
ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.
5. class);
MyDictionary dic = new MyDictionary();
6.
7. @Test
mockList.add(“one”);
8. public
Mockito.verify(mockList).add(arg.capture());
void whenUseInjectMocksAnnotation_thenCorrect() {
9. Mockito.when(wordMap.get(“aWord”)).thenReturn(“aMeaning”);
10.
11. assertEquals(“one”, arg.getValue());
assertEquals(“aMeaning”, dic.getMeaning(“aWord”));
12. }
8
7. Injecting a Mock Into a Spy
Similar to the above test, we might want to inject a mock into a spy:
1. @Mock
2. Map<String, String> wordMap;
3.
4. @Spy
5. MyDictionary spyDic = new MyDictionary();
However, Mockito doesn’t support injecting mocks into spies, and the
following test results in an exception:
1. @Test
2. public void whenUseInjectMocksAnnotation_thenCorrect() {
3. Mockito.when(wordMap.get(“aWord”)).thenReturn(“aMeaning”);
4.
5. assertEquals(“aMeaning”, spyDic.getMeaning(“aWord”));
6. }
If we want to use a mock with a spy, we can manually inject the mock
through a constructor:
Instead of using the annotation, we can now create the spy manually:
1. @Mock
2. Map<String, String> wordMap;
3. MyDictionary spyDic;
4. @BeforeEach
5. public void init() {
6. MockitoAnnotations.openMocks(this);
7. spyDic = Mockito.spy(new MyDictionary(wordMap));
8. }
9
8. Running Into NPE While Using Annotation
1. publish.subscribe(System.out::println);
2. publish.subscribe(System.out::println);
If we try running this code, nothing will happen. It’s not until we call connect()
that the Flux will start emitting:
1. publish.connect();
10
9. Notes
11
10. Conclusion
12
2. Mockito When/Then Examples
13
1. Overview
14
2. The Examples
15
Configure the behavior of multiple calls:
16
3. Conclusion
The goal of this chapter is simply to have this information readily available.
17
3. Mockito’s Mock Methods
18
1. Overview
In this chapter, we’ll illustrate the various uses of the standard static mock
methods of the Mockito API.
19
2. Simple Mocking
The simplest overloaded variant of the mock method is the one with a
single parameter for the class to be mocked:
1. MyList listMock
public static <T>
= mock(MyList.class);
T mock(Class<T> classToMock)
2. when(listMock.add(anyString())).thenReturn(false);
1. public static
boolean added =
<T>
listMock.add(randomAlphabetic(6));
T mock(Class<T> classToMock)
The following code confirms that we invoked the add method on the
mock. The invocation returns a value that matches the expectation we set
before:
1. MyList listMock
public static <T>
= mock(MyList.class);
T mock(Class<T> classToMock)
2. when(listMock.add(anyString())).thenReturn(false);
20
3. Mocking With Mock’s Name
In this section, we’ll cover another variant of the mock method, which is
provided with an argument specifying the name of the mock:
Generally speaking, the name of a mock has nothing to do with the working
code. However, it may be helpful in debugging, as we use the mock’s name
to track down verification errors.
1. MyList
public listMock = mock(MyList.class,
static <T> “myMock”);
T mock(Class<T> classToMock)
Then we’ll set an expectation on a method of the mock, and execute it:
1. when(listMock.add(anyString())).thenReturn(false);
public static <T> T mock(Class<T> classToMock)
2. listMock.add((6));
Next, we’ll call the verification inside the assertThatThrownBy, and verify
the instance of the exception thrown:
21
Further, we can also verify the exception’s message that it should contain
the information about the mock:
1. org.mockito.exceptions.verification.TooLittleActualInvocations:
public static <T> T mock(Class<T> classToMock)
2. myMock.add(<any>);
3. Wanted 2 times:
4. at com.baeldung.mockito.MockitoMockTest
5. .whenUsingMockWithName_thenCorrect(MockitoMockTest.java:...)
6. but was 1 time:
7. at com.baeldung.mockito.MockitoMockTest
8. .whenUsingMockWithName_thenCorrect(MockitoMockTest.java:...)
As we can see, the exception message includes the mock’s name, which
will be useful for finding the failure point in case of an unsuccessful
verification.
22
4. Mocking With Answer
Here we’ll demonstrate the use of a mock variant in which we’ll configure
the strategy for the mock’s answers to interaction at creation time. This
mock method’s signature in the Mockito documentation looks like the
following:
1. public
public static
static<T>
<T>T Tmock(Class<T> classToMock,
mock(Class<T> Answer defaultAnswer)
classToMock)
We’ll use the CustomAnswer class above for the generation of a mock:
1. public listMock
MyList static <T> T mock(Class<T> new
= mock(MyList.class, classToMock)
CustomAnswer());
1. public static
boolean added = <T> T mock(Class<T> classToMock)
listMock.add(randomAlphabetic(6));
The following verification and assertion confirm that the mock method with
an Answer argument worked as expected:
1. verify(listMock).add(anyString());
public static <T> T mock(Class<T> classToMock)
2. assertThat(added).isFalse();
23
5. Mocking With MockSettings
The final mock method we’ll cover in this chapter is the variant with a
parameter of the MockSettings type. We use this overloaded method to
provide a non-standard mock.
1. MockSettings
public staticcustomSettings = withSettings().defaultAnswer(new
<T> T mock(Class<T> classToMock)
2. CustomAnswer());
1. MyList
public listMock
static <T>
= mock(MyList.class,
T mock(Class<T> customSettings);
classToMock)
Similar to the preceding section, we’ll invoke the add method of a MyList
instance, and verify that the mock method with a MockSettings argument
works as expected:
1. boolean added =
public static listMock.add(randomAlphabetic(6));
<T> T mock(Class<T> classToMock)
2.
3. verify(listMock).add(anyString());
4. assertThat(added).isFalse();
24
6. Conclusion
25
4. Mockito Verify Method
26
1. Overview
27
2. The Examples
28
Verify the order of interactions:
29
Verify interaction with flexible/any argument:
30
3. Conclusion
31
5. Mockito ArgumentMatchers
32
1. Overview
In this chapter, we’ll learn how to use the ArgumentMatcher, and discuss
how it differs from the ArgumentCaptor.
33
2. Maven Dependencies
1. <dependency>
2. <groupId>org.mockito</groupId>
3. <artifactId>mockito-core</artifactId>
4. <version>5.3.1</version>
5. <scope>test</scope>
6. </dependency>
34
3. ArgumentMatchers
1. doReturn(“Flower”).when(flowerService).analyze(“poppy”);
In the above example, the String “Flower” is returned only when the
analyze method of FlowerService receives the String “poppy.”
1. when(flowerService.analyze(anyString())).thenReturn(“Flower”);
Now, because of the anyString argument matcher, the result will be the
same no matter what value we pass to analyze. ArgumentMatchers allow
us flexible verification or stubbing.
1. when(flowerService.isABigFlower(“poppy”, anyInt())).
2. thenReturn(true);
35
We can verify this by running the below test:
1. assertThrows(InvalidUseOfMatchersException.class,
2. () -> when(flowerService.isABigFlower(“poppy”, anyInt())).
3. thenReturn(true));
To fix this and keep the String name “poppy” as desired, we’ll use eq
matcher:
1. when(flowerService.isABigFlower(eq(“poppy”), anyInt())).
2. thenReturn(true);
1. when(flowerService.isABigFlower(eq(“poppy”), anyInt())).
2. thenReturn(true);
3.
4. Flower flower = new Flower(“poppy”, 15);
5.
6. Boolean response = flowerController.isABigFlower(flower);
7. assertThat(response).isTrue();
As per the second point, Mockito will detect the misplaced argument and
throw an InvalidUseOfMatchersException.
1. flowerController.isAFlower(“poppy”);
2.
3. String orMatcher = or(eq(“poppy”), endsWith(“y”));
4. assertThrows(InvalidUseOfMatchersException.class, () ->
5. verify(flowerService).analyze(orMatcher));
36
The way we’d implement the above code is:
1. verify(flowerService).analyze(or(eq(“poppy”), endsWith(“y”)));
37
4. Custom Argument Matcher
Creating our own matcher allows us to select the best possible approach
for a given scenario, and produce high-quality tests that are clean and
maintainable.
Since the Message is constructed inside the method under test, we must
use any as the matcher.
This approach doesn’t let us validate the data inside the Message, which
can be different from the data inside the MessageDTO.
38
To use our matcher, we need to modify our test and replace any by argThat:
Now we know our Message instance will have the same data as our
MessageDTO.
39
5. Custom Argument Matcher vs ArgumentCaptor
40
6. Conclusion
41
6. Mockito – Using Spies
42
1. Overview
In this chapter, we’ll illustrate how to make the most out of spies in
Mockito.
We’ll talk about the @Spy annotation, and how to stub a spy. Finally, we’ll
go into the difference between Mock and Spy.
43
2. Simple Spy Example
This will allow us to call all the normal methods of the object, while still
tracking every interaction, just as we would with a mock.
1. @Test
2. void givenUsingSpyMethod_whenSpyingOnList_thenCorrect() {
3. List<String> list = new ArrayList<String>();
4. List<String> spyList = spy(list);
5.
6. spyList.add(“one”);
7. spyList.add(“two”);
8.
9. verify(spyList).add(“one”);
10. verify(spyList).add(“two”);
11.
12. assertThat(spyList).hasSize(2);
13. }
Note how the real method add() is actually called, and how the size of
spyList becomes 2.
44
3. The @Spy Annotation
Next, let’s see how to use the @Spy annotation. We can use the @Spy
annotation instead of spy():
1. @Spy
2. List<String> spyList = new ArrayList<String>();
3.
4. @Test
5. void givenUsingSpyAnnotation_whenSpyingOnList_thenCorrect() {
6. spyList.add(“one”);
7. spyList.add(“two”);
8.
9. verify(spyList).add(“one”);
10. verify(spyList).add(“two”);
11.
12. assertThat(aSpyList).hasSize(2);
13. }
45
4. Stubbing a Spy
Now let’s see how to stub a Spy. We can configure/override the behavior
of a method using the same syntax we would use with a mock.
1. @Test
2. void givenASpy_whenStubbingTheBehaviour_thenCorrect() {
3. List<String> list = new ArrayList<String>();
4. List<String> spyList = spy(list);
5.
6. assertEquals(0, spyList.size());
7.
8. doReturn(100).when(spyList).size();
9. assertThat(spyList).hasSize(100);
10. }
46
5. Mock vs Spy in Mockito
Let’s discuss the difference between Mock and Spy in Mockito. We won’t
examine the theoretical differences between the two concepts, just how
they differ within Mockito itself.
When Mockito creates a mock, it does so from the Class of a Type, not
from an actual instance. The mock simply creates a bare-bones shell
instance of the Class, entirely instrumented to track interactions with it.
On the other hand, the spy will wrap an existing instance. It’ll still behave
in the same way as the normal instance; the only difference is that it’ll also
be instrumented to track all the interactions with it.
1. @Test
2. void whenCreateMock_thenCreated() {
3. List mockedList = mock(ArrayList.class);
4. mockedList.add(“one”);
5. verify(mockedList).add(“one”);
6. assertThat(mockedList).hasSize(0);
7. }
As we can see, adding an element into the mocked list doesn’t actually
add anything; it just calls the method with no other side effects.
A spy, on the other hand, will behave differently; it’ll actually call the real
implementation of the add method, and add the element to the underlying
list:
1. @Test
2. void whenCreateSpy_thenCreate() {
3. List spyList = Mockito.spy(new ArrayList());
4.
5. spyList.add(“one”);
6. Mockito.verify(spyList).add(“one”);
7.
8. assertThat(spyList).hasSize(1);
9. }
47
6. Understanding the Mockito NotAMockException
In this final section, we’ll learn about the Mockito NotAMockException. This
exception is one of the common exceptions we’ll likely encounter when
misusing mocks or spies.
When we run this code snippet, we’ll get the following error:
1. org.mockito.exceptions.misusing.NotAMockException:
2. Argument passed to when() is not a mock!
3. Example of correct stubbing:
4. doThrow(new RuntimeException()).when(mock).someMethod();
Thankfully, it’s quite clear from the Mockito error message what the
problem is here. In our example, the list object isn’t a mock. The Mockito
when() method expects a mock or spy object as the argument.
As we can also see, the Exception message even describes what a correct
invocation should look like. Now that we have a better understanding of
what the problem is, let’s fix it by following the recommendation:
Our example now behaves as expected, and we no longer see the Mockito
NotAMockException.
48
7. Conclusion
We learned how to create a spy, use the @Spy annotation, stub a spy, and
finally, the difference between Mock and Spy.
49
7. Using Mockito ArgumentCaptor
50
1. Overview
51
2. Using ArgumentCaptor
For example, consider an EmailService class with a send method that we’d
like to test:
52
2.1. Set Up the Unit Test
1. @ExtendWith(MockitoExtension.class)
2. class EmailServiceUnitTest {
3.
4.
5. @Mock
6. DeliveryPlatform platform;
7.
8.
9. @InjectMocks
10. EmailService emailService;
11.
12. ...
13. }
Second, let’s add a new ArgumentCaptor field of type Email to store our
captured argument:
1. @Captor
2. ArgumentCaptor<Email> emailCaptor;
Third, let’s use verify() with the ArgumentCaptor to capture the Email:
1. verify(platform).deliver(emailCaptor.capture());
53
We can then get the captured value, and store it as a new Email object:
Finally, let’s see the whole test with an assert to inspect the captured Email
object:
1. @Test
2. void whenDoesSupportHtml_expectHTMLEmailFormat() {
3. String to = “[email protected]”;
4. String subject = “Using ArgumentCaptor”;
5. String body = “Hey, let’use ArgumentCaptor”;
6.
7.
8. emailService.send(to, subject, body, true);
9.
10.
11. verify(platform).deliver(emailCaptor.capture());
12. Email value = emailCaptor.getValue();
13. assertThat(value.getFormat()).isEqualTo(Format.HTML);
14. }
54
3. Avoiding Stubbing
In contrast to the first test, notice how we have to perform an extra assert
on the last line to do the same as eq(credentials).
55
3.2. Reduced Defect Localization
1. org.mockito.exceptions.base.MockitoException:
2. No argument value was captured!
56
4. Conclusion
57
8. Mocking Void Methods With
Mockito
58
1. Overview
In this short chapter, we’ll focus on mocking void methods with Mockito.
As with other chapters focused on the Mockito framework (such as
Mockito Verify, Mockito When/Then, and Mockito’s Mock Methods), the
MyList class shown below will be used as the collaborator in test cases.
59
2. Simple Mocking and Verifying
1. @Test
2. public void whenAddCalled_thenVerified() {
3. MyList myList = mock(MyList.class);
4. doNothing().when(myList).add(isA(Integer.class), isA(String.
5. class));
6. myList.add(0, “”);
7.
8. verify(myList, times(1)).add(0, “”);
9. }
1. @Test
2. void whenAddCalled_thenVerified() {
3. MyList myList = mock(MyList.class);
4. myList.add(0, “”);
5.
6. verify(myList, times(1)).add(0, “”);
7. }
1. @Test
2. void givenNull_whenAddCalled_thenThrowsException() {
3. MyList myList = mock(MyList.class);
4. assertThrows(Exception.class, () -> {
5. doThrow().when(myList).add(isA(Integer.class), isNull());
6. });
7. myList.add(0, null);
8. }
60
3. Argument Capture
In the example above, we used the verify() method to check the arguments
passed to add().
1. @Test
2. void givenArgumentCaptor_whenAddCalled_thenValueCaptured() {
3. MyList myList = mock(MyList.class);
4.
5. ArgumentCaptor<String> valueCapture = ArgumentCaptor.
6. forClass(String.class);
7. doNothing().when(myList).add(any(Integer.class), valueCapture.
8. capture());
9.
10. myList.add(0, “captured”);
11.
12. assertEquals(“captured”, valueCapture.getValue());
13. }
61
4. Answering a Call to Void
For these situations, we can use Mockito’s Answer to add the behavior we
need:
1. @Test
webClient.get()
2. void
.uri(“/products”)
givenDoAnswer_whenAddCalled_thenAnswered() {
3. .retrieve()
MyList myList = mock(MyList.class);
4. .bodyToMono(String.class)
5. .block();
doAnswer(invocation -> {
6. Object arg0 = invocation.getArgument(0);
7. verifyCalledUrl(“/products”);
Object arg1 = invocation.getArgument(1);
8.
9. assertEquals(3, arg0);
10. assertEquals(“answer me”, arg1);
11. return null;
12. }).when(myList).add(any(Integer.class), any(String.class));
13.
14. myList.add(3, “answer me”);
15. }
62
5. Partial Mocking
1. @Test
2. void givenDoCallRealMethod_whenAddCalled_thenRealMethodCalled() {
3. MyList myList = mock(MyList.class);
4.
5. doCallRealMethod().when(myList).add(any(Integer.class),
6. any(String.class));
7. myList.add(1, “real”);
8.
9. verify(myList, times(1)).add(1, “real”);
10. }
This way, we can call the actual method and verify it at the same time.
63
6. Conclusion
64
7. Conclusion
Along the way, we covered various types and formats of query parameters.
Finally, we wrapped up by changing the default encoding mode of the URL
builder.
As always, all of the code snippets from the chapter are available over on
GitHub repository.
65
9. Mocking Static Methods With
Mockito
66
1. Overview
In this chapter, we’ll take a look at how we can now mock static methods
using the latest version of Mockito.
67
2. A Simple Static Utility Class
68
3. A Quick Word on Testing Static Methods
Generally speaking, some might say that when writing clean object-
orientated code, we shouldn’t need to mock static classes. This could
typically hint at a design issue or code smell in our application.
Why? First, a class depending on a static method has tight coupling, and
second, it nearly always leads to code that’s difficult to test. Ideally, a class
shouldn’t be responsible for obtaining its dependencies, and if possible,
they should be externally injected.
69
4. Mocking a No Argument Static Method
Let’s go ahead and see how we can mock the name method from our
StaticUtils class:
1. @Test
2. void givenStaticMethodWithNoArgs_whenMocked_
3. thenReturnsMockSuccessfully() {
4. assertThat(StaticUtils.name()).isEqualTo(“Baeldung”);
5.
6.
7. try (MockedStatic<StaticUtils> utilities = Mockito.
8. mockStatic(StaticUtils.class)) {
9. utilities.when(StaticUtils::name).thenReturn(“Eugen”);
10 assertThat(StaticUtils.name()).isEqualTo(“Eugen”);
11. }
12.
13.
14. assertThat(StaticUtils.name()).isEqualTo(“Baeldung”);
15. }
Therefore, in our unit test above, the utilities variable represents a mock
with a thread-local explicit scope. It’s important to note that scoped
mocks must be closed by the entity that activates the mock. This is why
we define our mock within a try-with-resources construct, so that the
mock is closed automatically when we finish with our scoped block.
This is a particularly nice feature, since it assures that our static mock
remains temporary. As we know, if we’re playing around with static method
calls during our test runs, this will likely lead to adverse effects on our test
results due to the concurrent and sequential nature of running tests.
On top of this, another nice side effect is that our tests will still run quite
fast, since Mockito doesn’t need to replace the classloader for every test.
In our example, we reiterate this point by checking before and after our
scoped block that our static method name returns a real value.
70
5. Mocking a Static Method With Arguments
Now let’s see another common use case when we need to mock a method
that has arguments:
1. @Test
2. void givenStaticMethodWithArgs_whenMocked_
3. thenReturnsMockSuccessfully() {
4. assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4,
5. 5);
6.
7.
8. try (MockedStatic<StaticUtils> utilities = Mockito.
9. mockStatic(StaticUtils.class)) {
10 utilities.when(() -> StaticUtils.range(2, 6))
11. .thenReturn(Arrays.asList(10, 11, 12));
12.
13.
14. assertThat(StaticUtils.range(2, 6)).containsExactly(10,
15. 11, 12);
16. }
17.
18.
19. assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4,
20. 5);
21. }
Here we follow the same approach, but this time we use a lambda
expression inside our when clause where we specify the method along
with any arguments that we want to mock. Pretty straightforward!
71
6. Conclusion
72
10. Mock Final Classes and Methods
With Mockito
73
1. Overview
In this short chapter, we’ll focus on how to mock final classes and methods
using Mockito.
74
2. Mock a Final Method
Once we’ve properly configured Mockito, we can mock a final method like
any other:
1. @Test
2. public void whenMockFinalMethod_thenMockWorks() {
3.
4.
5. MyList myList = new MyList();
6.
7.
8. MyList mock = mock(MyList.class);
9. when(mock.finalMethod()).thenReturn(1);
10
11.
12. assertThat(mock.finalMethod()).isNotZero();
13. }
75
3. Mock a Final Class
1. @Test
2. public void whenMockFinalClass_thenMockWorks() {
3.
4.
5. FinalList mock = mock(FinalList.class);
6. when(mock.size()).thenReturn(2);
7.
8.
9. assertThat(mock.size()).isNotEqualTo(1);
10. }
Similar to the test above, we’ll create a concrete instance and a mock
instance of our final class, mock a method, and verify that the mocked
instance behaves differently.
76
4. Conclusion
In this quick chapter, we covered how to mock final classes and methods
with Mockito by using a Mockito extension.
77
11. Mocking Exception Throwing
Using Mockito
78
1. Overview
1. class MyDictionary {
2.
3. private Map<String, String> wordMap;
4.
5.
6. public void add(String word, String meaning) {
7. wordMap.put(word, meaning);
8. }
9.
10.
11. public String getMeaning(String word) {
12. return wordMap.get(word);
13. }
14. }
79
2. Non-Void Return Type
First, if our method return type isn’t void, we can use when().thenThrow():
1. @Test
2. void givenNonVoidReturnType_whenUsingWhenThen_
3. thenExceptionIsThrown() {
4. MyDictionary dictMock = mock(MyDictionary.class);
5. when(dictMock.getMeaning(anyString())).
6. thenThrow(NullPointerException.class);
7.
8. assertThrows(NullPointerException.class, () -> dictMock.
9. getMeaning(“word”));
10. }
80
3. Void Return Type
1. @Test
2. void givenVoidReturnType_whenUsingDoThrow_thenExceptionIsThrown()
3. {
4. MyDictionary dictMock = mock(MyDictionary.class);
5. doThrow(IllegalStateException.class).when(dictMock)
6. .add(anyString(), anyString());
7.
8. assertThrows(IllegalStateException.class, () -> dictMock.
9. add(“word”, “meaning”));
10. }
We can’t use when().thenThrow() with the void return type, as the compiler
doesn’t allow void methods inside brackets.
81
4. Exception as an Object
1. @Test
2. void givenNonVoidReturnType_
3. whenUsingWhenThenAndExeceptionAsNewObject_thenExceptionIsThrown()
4. {
5. MyDictionary dictMock = mock(MyDictionary.class);
6. when(dictMock.getMeaning(anyString())).thenThrow(new
7. NullPointerException(“Error occurred”));
8.
9. assertThrows(NullPointerException.class, () -> dictMock.
10. getMeaning(“word”));
11. }
1. @Test
2. void givenNonVoidReturnType_
3. whenUsingDoThrowAndExeceptionAsNewObject_thenExceptionIsThrown() {
4. MyDictionary dictMock = mock(MyDictionary.class);
5. doThrow(new IllegalStateException(“Error occurred”)).
6. when(dictMock)
7. .add(anyString(), anyString());
8.
9. assertThrows(IllegalStateException.class, () -> dictMock.
10. add(“word”, “meaning”));
11. }
82
5. Spy
We can also configure Spy to throw an exception the same way we did with
the mock:
1. @Test
2. void givenSpyAndNonVoidReturnType_whenUsingWhenThen_
3. thenExceptionIsThrown() {
4. MyDictionary dict = new MyDictionary();
5. MyDictionary spy = Mockito.spy(dict);
6. when(spy.getMeaning(anyString())).
7. thenThrow(NullPointerException.class);
8.
9. assertThrows(NullPointerException.class, () -> spy.
10. getMeaning(“word”));
11. }
83
6. Conclusion
84
12. Mockito and JUnit 5 – Using
ExtendWith
85
1. Overview
In this quick chapter, we’ll demonstrate how to integrate Mockito with the
JUnit 5 extension model. To learn more about the JUnit 5 extension model,
have a look at this article.
86
2. Maven Dependencies
Let’s add the JUnit 5 (jupiter) and mockito dependencies to our pom.xml:
1. <dependency>
2. <groupId>org.junit.jupiter</groupId>
3. <artifactId>junit-jupiter-engine</artifactId>
4. <version>5.9.2</version>
5. <scope>test</scope>
6. </dependency>
7. <dependency>
8. <groupId>org.mockito</groupId>
9. <artifactId>mockito-core</artifactId>
10. <version>5.3.1</version>
11. <scope>test</scope>
12. </dependency>
87
3. Mockito Extension
1. <dependency>
2. <groupId>org.mockito</groupId>
3. <artifactId>mockito-junit-jupiter</artifactId>
4. <version>5.3.1</version>
5. <scope>test</scope>
6. </dependency>
88
4. Building the Test Class
Let’s build our test class, and attach the Mockito extension to it:
1. @ExtendWith(MockitoExtension.class)
2. class UserServiceUnitTest {
3.
4.
5. UserService userService;
6.
7.
8. // ...
9. }
We can use the @Mock annotation to inject a mock for an instance variable
that we can use anywhere in the test class:
1. @BeforeEach
2. void init(@Mock SettingRepository settingRepository) {
3. userService = new DefaultUserService(userRepository,
4. settingRepository, mailClient);
5.
6. lenient().when(settingRepository.getUserMinAge()).
7. thenReturn(10);
8.
9. when(settingRepository.getUserNameMinLength()).thenReturn(4);
10.
11. lenient().when(userRepository.
12. isUsernameAlreadyExists(any(String.class)))
13. .thenReturn(false);
14. }
89
Please note the use of lenient() here. Mockito throws an
UnsupportedStubbingException when an initialized mock isn’t called by
one of the test methods during execution. We can avoid this strict stub
checking by using this method when initializing the mocks.
1. @Test
2. void givenValidUser_whenSaveUser_thenSucceed(@Mock MailClient
3. mailClient) {
4. // Given
5. user = new User(“Jerry”, 12);
6. when(userRepository.insert(any(User.class))).then(new
7. Answer<User>() {
8. int sequence = 1;
9.
10. @Override
11. public User answer(InvocationOnMock invocation) throws
12. Throwable {
13. User user = (User) invocation.getArgument(0);
14. user.setId(sequence++);
15. return user;
16. }
17. });
18.
19.
20. userService = new DefaultUserService(userRepository,
21. settingRepository, mailClient);
22.
23.
24. // When
25. User insertedUser = userService.register(user);
26.
27. // Then
28. verify(userRepository).insert(user);
29. assertNotNull(user.getId());
30. verify(mailClient).sendUserRegistrationMail(insertedUser);
31. }
Note that the MailClient mock we inject as a test parameter will NOT be the
same instance we injected in the init method.
90
5. Conclusion
All of the code used in this chapter can be found on our GitHub project.
91