Mockito mock examples

Filed Under: Mockito

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.

Mockito mock method

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.

Mockito @Mock Annotation

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));
	}
	
}

Mockito @InjectMocks Annotation

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;
	}
	
}

Mockito spy() for partial mocking

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));
	}
	
}

Mockito @Spy Annotation

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<>();

Summary

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.

Comments

  1. Jith says:

    ​​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​.​

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages