Mockito mocking framework provides different ways to mock a class. Let’s look at different methods through which we can mock a class and stub its behaviors.
We can use Mockito class mock() method to create a mock object of a given class or interface. This is the simplest way to mock an object.
package com.journaldev.mockito.mock;
import java.util.List;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class MockitoMockMethodExample {
@SuppressWarnings("unchecked")
@Test
public void test() {
// using Mockito.mock() method
List<String> mockList = mock(List.class);
when(mockList.size()).thenReturn(5);
assertTrue(mockList.size()==5);
}
}
We are using JUnit 5 to write test cases in conjunction with Mockito to mock objects.
We can mock an object using @Mock annotation too. It’s useful when we want to use the mocked object at multiple places because we avoid calling mock() method multiple times. The code becomes more readable and we can specify mock object name that will be useful in case of errors. When using @Mock annotation, we have to make sure that we call MockitoAnnotations.initMocks(this)
to initialize the mocked object. We can do this in testing framework setup methods that are executed before the tests.
package com.journaldev.mockito.mock;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MockitoMockAnnotationExample {
@Mock
List<String> mockList;
@BeforeEach
public void setup() {
//if we don't call below, we will get NullPointerException
MockitoAnnotations.initMocks(this);
}
@SuppressWarnings("unchecked")
@Test
public void test() {
when(mockList.get(0)).thenReturn("JournalDev");
assertEquals("JournalDev", mockList.get(0));
}
}
When we want to inject a mocked object into another mocked object, we can use @InjectMocks annotation. @InjectMock creates the mock object of the class and injects the mocks that are marked with the annotations @Mock into it.
package com.journaldev.mockito.mock;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MockitoInjectMockAnnotationExample {
@Mock
List<String> mockList;
//@InjectMock creates an instance of the class and
//injects the mocks that are marked with the annotations @Mock into it.
@InjectMocks
Fruits mockFruits;
@BeforeEach
public void setup() {
//if we don't call below, we will get NullPointerException
MockitoAnnotations.initMocks(this);
}
@SuppressWarnings("unchecked")
@Test
public void test() {
when(mockList.get(0)).thenReturn("Apple");
when(mockList.size()).thenReturn(1);
assertEquals("Apple", mockList.get(0));
assertEquals(1, mockList.size());
//mockFruits names is using mockList, below asserts confirm it
assertEquals("Apple", mockFruits.getNames().get(0));
assertEquals(1, mockFruits.getNames().size());
mockList.add(1, "Mango");
//below will print null because mockList.get(1) is not stubbed
System.out.println(mockList.get(1));
}
}
class Fruits{
private List<String> names;
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
}
If we want to mock only specific behaviors and call the real methods for unstubbed behaviors, then we can create a spy object using Mockito spy() method.
package com.journaldev.mockito.mock;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
public class MockitoSpyMethodExample {
@Test
public void test() {
List<String> list = new ArrayList<>();
List<String> spyOnList = spy(list);
when(spyOnList.size()).thenReturn(10);
assertEquals(10, spyOnList.size());
//calling real methods since below methods are not stubbed
spyOnList.add("Pankaj");
spyOnList.add("Meghna");
assertEquals("Pankaj", spyOnList.get(0));
assertEquals("Meghna", spyOnList.get(1));
}
}
We can use @Spy annotation to spy on an object. Let’s look at a simple example.
package com.journaldev.mockito.mock;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
public class MockitoSpyAnnotationExample {
@Spy
Utils mockUtils;
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() {
when(mockUtils.process(1, 1)).thenReturn(5);
//mocked method
assertEquals(5, mockUtils.process(1, 1));
//real method called since it's not stubbed
assertEquals(20, mockUtils.process(19, 1));
}
}
class Utils{
public int process(int x, int y) {
System.out.println("Input Params = "+x+","+y);
return x+y;
}
}
Note that the @Spy annotation tries to call the no-args constructor to initialized the mocked object. If your class doesn’t have it then you will get the following error.
org.mockito.exceptions.base.MockitoException: Unable to initialize @Spy annotated field 'mockUtils'.
Please ensure that the type 'Utils' has a no-arg constructor.
at com.journaldev.mockito.mock.MockitoSpyAnnotationExample.setup(MockitoSpyAnnotationExample.java:18)
Also, note that Mockito cannot instantiate inner classes, local classes, abstract classes, and interfaces. So it’s always a good idea to provide an instance to spy on. Otherwise real methods might not get called and silently ignored. For example, if you specify a spy object as below:
@Spy
List<String> spyList;
You will notice that when you call add()
or get()
methods, real methods are not getting called. If you specify the spy object like below, then everything will work fine.
@Spy
List<String> spyList = new ArrayList<>();
Mockito mocking framework allows us to create mock object easily through different methods and annotations. We can also inject a mock object into another mock object, this is a very useful feature.
You can look at more Mockito examples from our GitHub Repository.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
if have given java class then we can easily understand the this tutorial
- Satya
How can we create nice mock using mockito?
- Gootam
Why your website is not a Progressive Web App? If you can add that PWA feature it will be helpful for me to access the website easily from my Homescreen and navigate offline.
- Jith