Mockito is a great framework for testing in java. I use it all the time and have done for many years now. It works hand in hand with dependnecy injection, a topic I covered in my last blog "Spring for Humans". However I sometimes find it's a victim of it's own success - there's a lot you can do with it so it's easy to forget how to do things!
So here's a cheat sheet which covers most of the features I use in Mockito.
Setting Up Mockito
Using JUnit <5 Annotations
import org.mockito.junit.MockitoJUnitRunner;
import org.junit.runner.RunWith;
@RunWith(MockJUnitRunner.class)
public class MyClassTest {
...
}
Using JUnit 5 Annotations
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class)
public class MyClassTest {
...
}
Using initMocks
Useful if you need more than one RunWith/Extend (e.g. SpringJunit4ClassRunner)
import org.mockito.MockitoAnnotations;
import org.junit.Before;
public class MyClassTest {
@Before
public void before() throw Exception {
Mockito.initMocks(this);
}
...
}
Creating Mocks and Spies
An easy way I use to remember the difference between mocks and spies is:
Mock: By default, all methods are stubbed unless you say otherwise.
Spy: By default, all methods use real implementation unless you say otherwise.
Creating a Mock
Use Annotations on Fields
There seems to be a consensus that this is the cleanest way to mock an object (which goes against my brain's aversion for field injection, but that's a story for another day).
import org.mockito.MockitoAnnotations;
import org.junit.Before;
import org.mockito.Mock;
public class MyClassTest {
@Mock
private MyClass myObject;
@Before
public void before() throw Exception {
Mockito.initMocks(this);
}
...
}
Create from Method
import org.mockito.MockitoAnnotations;
import org.junit.Before;
import org.mockito.Mock;
public class MyClassTest {
private MyClass myObject;
@Before
public void before() throw Exception {
Mockito.initMocks(this);
myObject = Mockito.mock(MyClass.class);
}
...
}
Create from Method using Initialised Object
Useful if you want a mock to be created from an object which has been constructed using a constructor.
import org.mockito.MockitoAnnotations;
import org.junit.Before;
import org.mockito.Mock;
public class MyClassTest {
private Person person = Person("name", 18);
@Before
public void before() throw Exception {
Mockito.initMocks(this);
person = Mockito.mock(person);
}
...
}
Creating a Spy
This is very similar to mocks.
Use Annotations on Fields
import org.mockito.MockitoAnnotations;
import org.junit.Before;
import org.mockito.Spy;
public class MyClassTest {
@Spy
private MyClass myObject;
@Before
public void before() throw Exception {
Mockito.initMocks(this);
}
...
}
Create from Method
import org.mockito.MockitoAnnotations;
import org.junit.Before;
import org.mockito.Spy;
public class MyClassTest {
private MyClass myObject;
@Before
public void before() throw Exception {
Mockito.initMocks(this);
myObject = Mockito.spy(MyClass.class);
}
...
}
Create from method using Initialised Object
Useful if you want a spy to be created from an object which has been constructed using a constructor.
import org.mockito.MockitoAnnotations;
import org.junit.Before;
import org.mockito.Spy;
public class MyClassTest {
private Person person = Person("name", 18);
@Before
public void before() throw Exception {
Mockito.initMocks(this);
person = Mockito.spy(person);
}
...
}
Injecting Mocks
Using @InjectMocks Annotation
public class InjectTest {
@Mock
private BlogRepository blogRepository;
@InjectMocks
private BlogPostService blogPostService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
System.out.println(blogPostService);
}
}
Using Constructor
public class InjectTest {
@Mock
private BlogRepository blogRepository;
@InjectMocks
private BlogPostService blogPostService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
blogPostService = new BlogPostService(blogRepository);
}
}
Stubbing a method
Returning from a stubbed Method
@Test
public void getAllBlogPosts_withBlogPostsInDb_returnsBlogPosts() {
List<BlogPost> expected = Arrays.asList(new BlogPost("Spring for humans"),
new BlogPost("Mockito Cheatsheet"));
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Mockito.when(blogRepository.getAllBlogPosts()).thenReturn(expected);
BlogPostService service = new BlogPostService(blogRepository);
List<BlogPost> actual = service.getAllBlogPosts();
assertEquals(expected, actual);
}
Providing an Alternative Implementation for a Method
@Test
public void getBlogPostById_withExistingBlogPostInDb_returnsBlogPost() {
BlogPost expected = new BlogPost("Spring for Humans");
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Mockito.when(blogRepository.getBlogPostById(Mockito.anyInt())).thenAnswer(invocationOnMock -> {
int id = invocationOnMock.getArgument(0);
if(id == 1) return Optional.of(expected);
else return Optional.empty();
});
BlogPostService service = new BlogPostService(blogRepository);
BlogPost actual = service.getBlogPostById(1).get();
assertEquals(expected, actual);
}
Throwing an Exception from a Method
@Test(expected = IllegalArgumentException.class)
public void getBlogPostById_withMissingBlogPost_throwsException() {
BlogPost expected = new BlogPost("Spring for Humans");
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Mockito.when(blogRepository.getBlogPostById(1)).thenThrow(new IllegalArgumentException());
BlogPostService service = new BlogPostService(blogRepository);
BlogPost actual = service.getBlogPostById(1).get();
}
Calling the Real Implementation
@Test
public void getBlogPostById_withMissingBlogPost_returnsEmpty() {
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Mockito.when(blogRepository.getBlogPostById(1)).thenCallRealMethod();
BlogPostService service = new BlogPostService(blogRepository);
Optional<BlogPost> actual = service.getBlogPostById(1);
assertFalse(actual.isPresent());
}
Using Deep Stubs
Deep stubs are used for methods which are chained, but you don't care about the intermediate values. These should be used sparingly, as discussed in the Mockito documentation.
@Test
public void checkIfDriverIsPostgres_withPostgresDriver_returnsTrue() {
Configuration configMock = Mockito.mock(Configuration.class);
RepositoryConfiguration repositoryConfigMock = Mockito.mock(RepositoryConfiguration.class);
Mockito.when(configMock.getRepositoryConfiguration()).thenReturn(repositoryConfigMock);
DatabaseConfiguration databaseConfigMock = Mockito.mock(DatabaseConfiguration.class);
Mockito.when(repositoryConfigMock.getDatabaseConfiguration()).thenReturn(databaseConfigMock);
DatabaseConfiguration.DriverConfiguration driverConfigMock = Mockito.mock(DatabaseConfiguration.DriverConfiguration.class);
Mockito.when(databaseConfigMock.getDriverConfiguration()).thenReturn(driverConfigMock);
Mockito.when(driverConfigMock.getDriverType()).thenReturn("postgres");
BlogRepository blogRepository = new BlogRepository(configMock);
boolean actual = blogRepository.checkIfDriverIsPostgres();
Assert.assertTrue(actual);
}
@Test
public void usingDeepStubs_checkIfDriverIsPostgres_withPostgresDriver_returnsTrue() {
Configuration configMock = Mockito.mock(Configuration.class, Mockito.RETURNS_DEEP_STUBS);
Mockito.when(configMock.getRepositoryConfiguration()
.getDatabaseConfiguration().getDriverConfiguration().getDriverType()).thenReturn("postgres");
BlogRepository blogRepository = new BlogRepository(configMock);
boolean actual = blogRepository.checkIfDriverIsPostgres();
Assert.assertTrue(actual);
}
Stubbing a Void Method
Providing an Alternative Implementation for a Method
@Test
public void getAllBlogPosts_withBlogPostsInDb_callsVerifyConnectionToDatabaseIsAlive() {
Configuration configMock = Mockito.mock(Configuration.class);
BlogRepository blogRepository = new BlogRepository(configMock);
AtomicBoolean verifyMethodCalled = new AtomicBoolean(false);
Mockito.doAnswer(invocationOnMock -> {
verifyMethodCalled.set(true);
return null;
}).when(configMock).verifyConnectionToDatabaseIsAlive();
blogRepository.getAllBlogPosts();
assertTrue(verifyMethodCalled.get());
}
Throwing an Exception from a Method
@Test(expected = DatabaseDownException.class)
public void getAllBlogPosts_withConnectionToDbDown_throwsException() {
Configuration configMock = Mockito.mock(Configuration.class);
BlogRepository blogRepository = new BlogRepository(configMock);
AtomicBoolean verifyMethodCalled = new AtomicBoolean(false);
Mockito.doThrow(new DatabaseDownException()).when(configMock).verifyConnectionToDatabaseIsAlive();
blogRepository.getAllBlogPosts();
}
Calling the Real Implementation
@Test
public void getAllBlogPosts_withBlogPostsInDb_returnsBlogPosts() {
Configuration configMock = Mockito.mock(Configuration.class);
BlogRepository blogRepository = new BlogRepository(configMock);
AtomicBoolean verifyMethodCalled = new AtomicBoolean(false);
Mockito.doCallRealMethod().when(configMock).verifyConnectionToDatabaseIsAlive();
blogRepository.getAllBlogPosts();
}
Matchers
Using a Real Parameter
@Test
public void getBlogPostByAuthorAndAfterDate_withExistingBlogPostsInDb_returnsBlogPosts() {
List<BlogPost> expected = Collections.singletonList(new BlogPost("Spring for Humans"));
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Date date = new Date();
String author = "Shane";
Mockito.when(blogRepository.getBlogPostsByAuthorAndAfterDate(author, date)).thenReturn(expected);
BlogPostService service = new BlogPostService(blogRepository);
List<BlogPost> actual = service.getBlogPostsByAuthorAndAfterDate(author, date);
assertEquals(expected, actual);
}
Using any()
@Test
public void getBlogPostByAuthorAndAfterDate_withoutMatchingBlogPostsInDb_returnsEmptyList() {
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Mockito.when(blogRepository.getBlogPostsByAuthorAndAfterDate(Mockito.any(), Mockito.any())).thenReturn(Collections.emptyList());
BlogPostService service = new BlogPostService(blogRepository);
List<BlogPost> actual = service.getBlogPostsByAuthorAndAfterDate("any author", new Date());
assertTrue(actual.isEmpty());
}
Using anyClass()
@Test
public void getBlogPostByAuthorAndAfterDate_withMatchingAuthorAndDate_returnsPostsSortedByDate() {
BlogPost first = new BlogPost("Spring for Humans", "Shane", new Date(5));
BlogPost second = new BlogPost("Mockito Cheatsheet", "Shane", new Date(6));
BlogPost third = new BlogPost("?", "Shane", new Date(7));
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
// Good for overloaded methods, you can specify type of params so the call isn't ambiguous.
Mockito.when(blogRepository.getBlogPostsByAuthorAndAfterDate(Mockito.any(String.class), Mockito.any(Date.class)))
.thenReturn(Arrays.asList(second, third, first));
BlogPostService service = new BlogPostService(blogRepository);
List<BlogPost> expected = Arrays.asList(first, second, third);
List<BlogPost> actual = service.getBlogPostsByAuthorAndAfterDate("any author", new Date());
assertEquals(expected.get(0), actual.get(0));
assertEquals(expected.get(1), actual.get(1));
assertEquals(expected.get(2), actual.get(2));
}
Using eq()
@Test
public void getBlogPostByAuthorAndAfterDate_withMatchingAuthorButFutureDate_returnsEmptyList() {
List<BlogPost> expected = Collections.singletonList(new BlogPost("Spring for Humans"));
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Date date = new Date();
Mockito.when(blogRepository.getBlogPostsByAuthorAndAfterDate(Mockito.any(), Mockito.eq(date))).thenReturn(expected);
BlogPostService service = new BlogPostService(blogRepository);
List<BlogPost> actual = service.getBlogPostsByAuthorAndAfterDate("any author", date);
assertTrue(actual.isEmpty());
}
Using Custom Matcher
@Test
public void checkIfBlogPostHasBeenSaved_withBlogPost_returnsTrue() {
BlogPost post = new BlogPost("Spring for Humans", "Shane", new Date(5));
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
ArgumentMatcher<BlogPost> blogPostMatcher = passedBlogPost ->
"Shane".equals(passedBlogPost.getAuthor());
Mockito.when(blogRepository.checkIfBlogPostHasBeenSaved(Mockito.argThat(blogPostMatcher)))
.thenReturn(true);
BlogPostService service = new BlogPostService(blogRepository);
boolean actual = service.checkIfBlogPostHasBeenSaved(post);
assertTrue(actual);
}
Verify a Stubbed Method Has Been Called
@Test
public void getAllBlogPosts_withBlogPost_verifiesThatRepositoryWasCalled() {
List<BlogPost> expected = Arrays.asList(new BlogPost("Spring for humans"),
new BlogPost("Mockito Cheatsheet"));
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
Mockito.when(blogRepository.getAllBlogPosts()).thenReturn(expected);
BlogPostService service = new BlogPostService(blogRepository);
service.getAllBlogPosts();
Mockito.verify(blogRepository).getAllBlogPosts();
}
Verify a Stubbed Method Hasn't Been Called
@Test
public void getBlogPostById_withBlogPost_verifiesThatCorrectMethodWasCalled() {
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
BlogPost expoected = new BlogPost("Spring for humans");
Mockito.when(blogRepository.getBlogPostById(1)).thenReturn(Optional.of(expoected));
BlogPostService service = new BlogPostService(blogRepository);
service.getBlogPostById(1);
Mockito.verify(blogRepository, Mockito.never()).getBlogPostById(100);
Mockito.verify(blogRepository).getBlogPostById(1);
}
Capturing Arguments
@Test
public void getBlogPostById_withBlogPost_verifiesCorrectArgumentPassed() {
BlogRepository blogRepository = Mockito.mock(BlogRepository.class);
int expected = 1;
Mockito.when(blogRepository.getBlogPostById(expected))
.thenReturn(Optional.of(new BlogPost("Spring for humans")));
BlogPostService service = new BlogPostService(blogRepository);
ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
// act
service.getBlogPostById(expected);
Mockito.verify(blogRepository).getBlogPostById(captor.capture());
int actual = captor.getValue();
// assert
assertEquals(expected, actual);
}
Conclusion
Hopefully the snippets laid out here will help you quickly set up your mockito tests. The full examples can be seen here on GitHub.
Happy Coding!