Part 1 – What is Mock Object? What is Mockito?

What is a Mock Object?
In object-oriented programming, mock objects are simulated objects that mimic the behaviour of real objects in controlled ways. A programmer typically creates a mock object to test the behaviour of some other object, in much the same way that a car designer uses a crash test dummy to simulate the dynamic behaviour of a human in vehicle impacts.

When should I mock?
A unit test should test a single code path through a single method. When the execution of a method passes outside of that method, into another object, and back again, you have a dependency.

When you test that code path with the actual dependency, you are not unit testing; you are integration testing. While that’s good and necessary, it isn’t unit testing.

Mockito Framework
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.

Mockito is used to mock interfaces so that a dummy functionality can be added to a mock interface that can be used in unit testing.

More information can be found on below url:
https://site.mockito.org/

Enable Mockito Annotations
we need to enable the Mockito to use its annotation and functionality. There are 2 ways to enable the Mockito framework for our JUnit class.

1. MockitoJUnitRunner

We’ll need to annotate the JUnit test with a runner – MockitoJUnitRunner as in the following example:

@RunWith(MockitoJUnitRunner.class)
public class TestClass {
    ...
}

2. MockitoAnnotations.initMocks()
Alternatively, we can enable these annotations programmatically as well, by invoking MockitoAnnotations.initMocks() as in the following example:


@Before
public void init() {
     MockitoAnnotations.initMocks(this);
}
How to Mock Object with @Mock & @InjectMock annotations in Spring application?
Let’s create some business logic to write the test cases.

Service Layer –

package com.onlyfullstack.unittesting.service;

import com.onlyfullstack.unittesting.bean.Customer;
import com.onlyfullstack.unittesting.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;

public final class CustomerService {

    @Autowired
    public CustomerRepository repository;

    public boolean saveCustomer(Customer customer) {
        if (customer == null) {
            throw new IllegalArgumentException("Invalid Customer details passed.");
        }
        return repository.saveCusomer(customer);
    }

    public Customer getCustomer(Integer customerId) {
        if (customerId == null || customerId < 0) {
            throw new IllegalArgumentException("Invalid Customer details passed.");
        }
        return repository.getCustomer(customerId);
    }

    public void updateCustomer(Customer customer) {
        if (customer == null || customer.getId() < 0) {
            throw new IllegalArgumentException("Invalid Customer details passed.");
        }
        repository.updateCustomer(customer);
    }
}

Repository Layer-

package com.onlyfullstack.unittesting.repository;

import java.util.HashMap;
import java.util.Map;

import com.onlyfullstack.unittesting.bean.Customer;
import org.springframework.stereotype.Component;

@Component
public class CustomerRepository {

    private static Map<Integer, Customer> customerMap = new HashMap<>();

    {
        customerMap.put(1, new Customer(1, "ABC", "Pune"));
        customerMap.put(2, new Customer(2, "XYZ", "Pune"));
        customerMap.put(3, new Customer(3, "PQR", "Pune"));
        customerMap.put(4, new Customer(4, "MNO", "Pune"));
    }

    public boolean saveCusomer(Customer customer) {
        customerMap.put(customer.getId(), customer);
        return true;
    }

    public Customer getCustomer(Integer customerId) {
        return customerMap.get(customerId);
    }

    public void updateCustomer(Customer customer) {
        customerMap.put(customer.getId(), customer);
    }
}

As you can see CustomerRepository is Autowired in CustomerService class. So we need to use @InjectMocks and we will see why and how it works.

Test Class-

package com.onlyfullstack.unittesting.service;

import com.onlyfullstack.unittesting.bean.Customer;
import com.onlyfullstack.unittesting.repository.CustomerRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * This class contains usage of Mockito
 */
@RunWith(MockitoJUnitRunner.class)
public class CustomerServiceTest {

    @Mock
    CustomerRepository repository;

    @InjectMocks
    CustomerService customerService;

    @Test
    public void saveCustomer_withValidCustomer() {
        Customer customer = new Customer(6, "QQQ", "Mumbai");
        when(repository.saveCusomer(any())).thenReturn(true);
        Boolean save = customerService.saveCustomer(customer);
        assertThat(true, is(save));
        verify(repository, times(1)).saveCusomer(eq(customer));
    }

}

@Mock will create a mock implementation for the CustomerRepository
@InjectMocks will inject the mocks marked with @Mock to this instance when it is created

In the test method, we have added when then pattern that we are going to see in our next tutorial.

Source Code
Download the source code of JUnit tutorial from below git repository :
unit-testing-and-integration-testing-with-spring-boot

Let’s go to our next tutorial where we will discuss below points :

Part 2 – How to mock methods with Mockito?
 – How to mock methods?
1. when/then
2. when/thenThrow
3. when/thenAnswer
https://www.onlyfullstack.com/how-to-mock-methods-with-mockito/

Mockito Tutorial
https://www.onlyfullstack.com/mockito-tutorial/