Fork me on GitHub

Introduction

Mockito is a mocking framework for unit tests in Java. It lets you write tests with a clean and simple API.

During this workshop you will user Mockito 2.X

For more information, please visit:

Exercise

In this exercise you will test DefaultCommentFacade class. It uses:

  • UserService - to obtain current user
  • PerrsmisionService - to find out if user has permission to read/create comments
  • CommentService - to create and persist comments

A start point is DefaultCommentFacadeTest.java file.

Mockito Basics

Mockito allows you to create mocks programmatically:

UserService userServiceMock = Mockito.mock(UserService.class);

or with annotations:

@Mock
private UserService userServiceMock;

You can also use partial mock called spy. It is like real object but you can still stub some behaviour. But don't overuse this!!!

UserService userServiceSpy = Mockito.spy(UserService.class);
UserService userServiceSpy = Mockito.spy(new DefaultUserService());

@Spy
UserService userServiceSpy;

When you create a mock by annotations you can inject it to a tested class with annotations:

@InjectMocks
private ClassUnderTest underTest;

It is done automatically when you use MockitoJUnitTestRunner:

@RunWith(MockitoJUnitRunner.class)
public class DefaultCommentFacadeTest {
    // implementation here
}

or you can do it by yourself:

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

Of course you can create an object under test by hand and don't use injection mechanism at all.

Stubbing methods

When a mock is created, then you can define its behaviour:

CommentModel commentMock = mock(CommentModel.class);
CommentService commentServiceMock = mock(CommentService.class);
when(commentServiceMock.createComment(anyString())).thenReturn(commentMock);

Now after calling commentServiceMock.createComment("another string") it will return the commentMock. anyString() is an argument matcher (see: org.mockito.ArgumentMatchers) which substitutes any string. You can also use a specific argument:

CommentModel commentMock = mock(CommentModel.class);
CommentService commentServiceMock = mock(CommentService.class);
when(commentServiceMock.createComment("some string")).thenReturn(commentMock);

In this example calling commentServiceMock.createComment("another string") will return null. You can stub method to do more complex operations by using instances of the org.mockito.stubbing.Answer.

For more examples check here: Mockito examples and documentation.

Verification

Mocks allows you to check if some interaction have happened. Let's assume that the CommentFacade to add a new comment will use a CommentService#addComment(Model,CommentModel) method. In your test you want to check if a call of this method happened. You can do it like this:

CommentService commentServiceMock = mock(CommentService.class);
CommentFacade commentFacadeUnderTest = new DefaultCommentFacade(commentServiceMock);
commentFacadeUnderTest.addComment(any(), any());

verify(commentServiceMock).addComment(any(), any());

This will check if the addComment method was called once. verify method allows you to check not only for one invocation, but it has many variants:

verify(mockedObject, times(3));
verify(mockedObject, never());
verify(mockedObject, atLeast(3));
verify(mockedObject, atMost(3));

Argument captor

If you need to add some assertions to parameters which method was called you can use an org.mockito.ArgumentCaptor class:

CommentService commentServiceMock = mock(CommentService.class);
CommentFacade commentFacadeUnderTest = new DefaultCommentFacade(commentServiceMock);
commentFacadeUnderTest.addComment(mock(Model.class), "some string");

ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
verify(commentServiceMock).createComment(stringCaptor.capture());
asserThat(stringCaptor.getValue()).isEqualTo("some string");