Klimiec / Introduction-to-Mock-with-Mockito-

Introduction to Mock with Mockito

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Introduction to mocking/stubbing with Mockito

The Purpose of this project is an introduction to less common features of Mockito framework and test templates in IntelliJ IDEA.

I will start with fundamental things of mocking/stubbing in order to lay the ground for more advanced things. They will help us highlights problems we encounter on daily bases when working with Mockito and embraces solutions :-)

Agenda

Default behaviour of not stubbed method

When no stubbed, methods of mocks return zeros, falseys, empty collections or nulls - depends what is the return type of used method. It can lead to encountering NullPointerException.

java.lang.NullPointerException
    at domain.InvoiceService.issueInvoice(ItemService.java:10)
    at domain.a_missing_mock_for_organisation.ItemServiceTest.shouldIssueAnInvoiceWithSuccess(ItemServiceTest.java:24)

Code example here

Above stack trace informes us only about the line number where NullPointerException occurred. It isn’t obvious at first glance that the source of the problem was default value returned from unstubbed method that developer has forgotten to stub. What if we could get a more readable stack trace that help us track the bug right away. It turns out that Mockito has such feature - SmartNull.

SmartNulls

SmartNull produces much more descriptive exception message then NPE. It points exactly what unstubbed method on mock was called that lead to NPE.

org.mockito.exceptions.verification.SmartNullPointerException: 
You have a NullPointerException here:
-> at domain.InvoiceService.issueInvoice(ItemService.java:10)
because this method call was *not* stubbed correctly:
-> at domain.InvoiceService.issueInvoice(ItemService.java:10)
order.getOrganisation();


	at domain.InvoiceService.issueInvoice(ItemService.java:10)
	at domain.b_smart_null.InvoiceServiceTest.shouldIssueAnInvoiceWithSuccess(ItemServiceTest.java:28)

Code example here

To make mock returns SmartNull instead of null override default answer with RETURNS_SMART_NULLS flag

mock(Item.class, RETURNS_SMART_NULLS);

or

@Mock(answer = Answers.RETURNS_SMART_NULLS)
Item order;

We need to change default answer for every mock that we want to return smart nulls. Because of this ceremony not many people opt to use this feature.

It turns out that with a little work we can change default answer for all mock to RETURNS_SMART_NULLS with no additional repetitive work.

Mockito global configuration

Mockito provides a global configuration that we can use to change some default behavior. For instance, we can change default answer for unstubbed mock to RETURNS_SMART_NULLS.

In order to do this, we need to create class org.mockito.configuration.MockitoConfiguration (in test folder) that extends DefaultMockitoConfiguration.

public class MockitoConfiguration extends DefaultMockitoConfiguration{

    public Answer<Object> getDefaultAnswer() {
        return new ReturnsSmartNulls();
    }
}

Code example here

Deep stubbing

Sometimes when working with a badly design legacy system we encounter a situation where in order to tests something our mock has to return another mock to return something meaningful.

Example of ‘deep stubbing’

        Item order = mock(Item.class, RETURNS_SMART_NULLS);
        Organisation orderItem = mock(Organisation.class);

        when(order.getOrganisation()).thenReturn(orderItem);
        when(orderItem.getOrganisationId()).thenReturn(0l);

We can shorten deep stubbing creation with RETURNS_DEEP_STUBS

        Item order = mock(Item.class, RETURNS_DEEP_STUBS);
        when(order.getOrganisation().getOrganisationId()).thenReturn(0l);

More information here

Templates in intelliJ

IntelliJ provides templates for test methods and test classes. They are very helpfull in getting ride of repetive task such as:

  • add static import for Mockito and AssertJ
  • embeding comments for 'given-when-then' inside test method
Test method

In order to edit template for test method go to File | Settings | Editor | File and Code Templates. Choose 'code' tab and edit JUnit4 Test Method with following values.

@org.junit.Test
public void should${NAME}() {
  //given
  ${BODY}
  //when
  //then
}

To use template press Cltr + Insert inside test class and choose Test Method.

Test class

In order to edit template for test class go to File | Settings | Editor | File and Code Templates.

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

#parse("File Header.java") 
public class ${NAME} {
  ${BODY}
}    

To use template press Ctrl + Shift + T inside class and pick Create New Test ...

About

Introduction to Mock with Mockito


Languages

Language:Java 100.0%