DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How to Migrate From JUnit 4 to JUnit 5 Step by Step
  • Understanding the Two Schools of Unit Testing
  • IntelliJ Integration for Mockito
  • The Most Popular Technologies for Java Microservices Right Now

Trending

  • Introducing Graph Concepts in Java With Eclipse JNoSQL, Part 2: Understanding Neo4j
  • Monoliths, REST, and Spring Boot Sidecars: A Real Modernization Playbook
  • Securing the Future: Best Practices for Privacy and Data Governance in LLMOps
  • Using Python Libraries in Java
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. A Guide to Mocking With Mockito

A Guide to Mocking With Mockito

If you're thinking about trying Mockito out for unit testing, this article provides a comprehensive guide to injecting mocks and mocking methods, including void methods.

By 
Dilini Rajapaksha user avatar
Dilini Rajapaksha
·
Jun. 09, 17 · Tutorial
Likes (51)
Comment
Save
Tweet
Share
284.8K Views

Join the DZone community and get the full member experience.

Join For Free

Most of the classes we come across have dependencies, and oftentimes, methods delegate some work to other methods in other classes. These classes are our dependencies. When unit testing such methods, if we only use JUnit, our tests will also depend on those methods as well. We want the unit tests to be independent of all other dependencies.

  • Say we want to test the method addCustomer in the CustomerService class, and within this addCustomer method, the save method of the CustomerDao class is invoked. We don’t want to call the real implementation of the CustomerDao save() method for a few reasons:
    • We only want to test the logic inside the addCustomer() in isolation.
    • We may not yet have implemented it.
    • We don’t want the unit test of the addCustomer() fail if there is a defect in the save() method in the CustomerDao.
  • So we should somehow mock the behavior of the dependencies. This is where mocking frameworks come into play.
  • Mockito is what I use for just this, and in this post, we’ll see how to effectively use Mockito to mock those dependencies.

If you are new to unit testing with JUnit, please check out an earlier post of mine on How to write great unit tests with JUnit

What Is Mockito?

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.” Mockito Framework Site. N.p., n.d. Web. 28 Apr. 2017.

Injecting Mocks With Mockito

So, going back to the example above, how do we mock out the dependency using Mockito? Well, we could inject a mock to the class under test instead of the real implementation while we run our tests!

Let’s look at an example of a class under test which has a dependency on CustomerDao:

public class CustomerService {

    @Inject
    private CustomerDao customerDao;

    public boolean addCustomer(Customer customer){

    if(customerDao.exists(customer.getPhone())){
         return false;
    }

         return customerDao.save(customer);
    }
    public CustomerDao getCustomerDao() {
         return customerDao;
    }

    public void setCustomerDao(CustomerDao customerDao) {
         this.customerDao = customerDao;
    }

}


The following is the test that mocks the dependency using Mockito:

public class CustomerServiceTest {

    @Mock
    private CustomerDao daoMock;

    @InjectMocks
    private CustomerService service;

    @Before
    public void setUp() throws Exception {

         MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() {

         //assertion here
    }

}


Let’s look at the role of the annotations in the above example.

  • @Mock will create a mock implementation for the CustomerDao
  • @InjectMocks will inject the mocks marked with @Mock to this instance when it is created.
  • So when or where are these instances created? Well, it is done in this line, which resides in the setUp method:

MockitoAnnotations.initMocks(this);

  • So these instances would be created at the start of every test method of this test class.

Mocking Methods With Mockito

Great! Now we have successfully created and injected the mock, and now we should tell the mock how to behave when certain methods are called on it.

The when then pattern:

  • We do this in each of the test methods. The following line of code tells the Mockito framework that we want the save() method of the mock DAO instance to return true when passed in a certain customer instance.

when(dao.save(customer)).thenReturn(true);

  • when is a static method of the Mockito class, and it returns an OngoingStubbing<T> (T is the return type of the method that we are mocking — in this case, it is boolean).
  • So if we just extract that out to get ahold of the stub, it looks like this:

OngoingStubbing<Boolean> stub = when(dao.save(customer));

  • The following are some of the methods that we can call on this stub
    • thenReturn(returnValue)
    • thenThrow(exception)
    • thenCallRealMethod()
    • thenAnswer() - this could be used to set up smarter stubs and also mock the behavior of void methods as well (see How to mock void method behavior).
  • Simply putting this all in one line again: when(dao.save(customer)).thenReturn(true);
  • Do we really need to pass in an actual customer object to the save method here? No, we could use matchers like the following:when(dao.save(any(Customer.class))).thenReturn(true);
  • However, when there are multiple parameters to a method, we cannot mix matchers and actual objects. For example, we cannot do the following: Mockito.when(mapper.map(any(), "test")).thenReturn(new Something());

    This would compile without a complaint but would fail during runtime with an error saying: matchers can't be mixed with actual values in the list of arguments to a single
    method.
  • We either have to use matchers for all parameters or should pass in real values or objects.

Mock behavior of dependencies using Mockito.when:


package com.tdd;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class CustomerServiceTest {

    @Mock
    private CustomerDao daoMock;

    @InjectMocks
    private CustomerService service;

    @Before
    public void setUp() throws Exception {

        MockitoAnnotations.initMocks(this);
    }

     @Test
        public void testAddCustomer_returnsNewCustomer() {

            when(daoMock.save(any(Customer.class))).thenReturn(new Customer());

            Customer customer = new Customer();

            assertThat(service.addCustomer(customer), is(notNullValue()));

        }


    //Using Answer to set an id to the customer which is passed in as a parameter to the mock method.
    @Test
    public void testAddCustomer_returnsNewCustomerWithId() {

        when(daoMock.save(any(Customer.class))).thenAnswer(new Answer<Customer>() {

            @Override
            public Customer answer(InvocationOnMock invocation) throws Throwable {

                Object[] arguments = invocation.getArguments();

                if (arguments != null && arguments.length > 0 && arguments[0] != null){

                    Customer customer = (Customer) arguments[0];
                    customer.setId(1);

                    return customer;
                }

                return null;
            }
        });

        Customer customer = new Customer();

        assertThat(service.addCustomer(customer), is(notNullValue()));

    }

    //Throwing an exception from the mocked method
     @Test(expected = RuntimeException.class)
        public void testAddCustomer_throwsException() {

            when(daoMock.save(any(Customer.class))).thenThrow(RuntimeException.class);

            Customer customer = new Customer();

            service.addCustomer(customer);//

        }
}


Mocking Void Methods With Mockito

  1. doAnswer: If we want our mocked void method to do something (mock the behavior despite being void).
  2. doThrow: Then there is Mockito.doThrow() if you want to throw an exception from the mocked void method.

The following is an example of how to use it. Bear in mind, it isn't an ideal use case, but I wanted to illustrate the basic usage:

    @Test
    public void testUpdate() {

        doAnswer(new Answer<Void>() {

            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Object[] arguments = invocation.getArguments();
                if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {

                    Customer customer = (Customer) arguments[0];
                    String email = (String) arguments[1];
                    customer.setEmail(email);

                }
                return null;
            }
        }).when(daoMock).updateEmail(any(Customer.class), any(String.class));

        // calling the method under test
        Customer customer = service.changeEmail("old@test.com", "new@test.com");

        //some asserts
        assertThat(customer, is(notNullValue()));
        assertThat(customer.getEmail(), is(equalTo("new@test.com")));

    }

    @Test(expected = RuntimeException.class)
    public void testUpdate_throwsException() {

        doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));

        // calling the method under test
        Customer customer = service.changeEmail("old@test.com", "new@test.com");

    }
}


The Two Ways of Testing Void Methods With Mockito

Methods with return values can be tested by asserting the returned value, but how do we test void methods? The void method that you want to test could either be calling other methods to get things done, processing the input parameters, or maybe generating some values or all of it. With Mockito, you can test all of the above scenarios.

Verify With Mockito

A great thing about mocking is that we can verify that certain methods have been called on those mock objects during test execution — in addition to or in place of assertions — when the method under test is void.

  • There are two overloaded verify methods.
    • One that accepts only the mock object — we can use this if the method is supposed to be invoked only once.
    • The other accepts the mock and a VerificationMode — there are quite a few methods in the Mockito class that provide some useful verificationModes:
      • times(int wantedNumberOfInvocations)
      • atLeast( int wantedNumberOfInvocations )
      • atMost( int wantedNumberOfInvocations )
      • calls( int wantedNumberOfInvocations )
      • only( int wantedNumberOfInvocations )
      • atLeastOnce()
      • never()

Mockito.verify:

package com.tdd;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class CustomerServiceTest {

    @Mock
    private CustomerDao daoMock;

    @InjectMocks
    private CustomerService service;

    @Before
    public void setUp() throws Exception {

        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() {

        when(daoMock.save(any(Customer.class))).thenReturn(true);

        Customer customer=new Customer();
        assertThat(service.addCustomer(customer), is(true));

        //verify that the save method has been invoked
        verify(daoMock).save(any(Customer.class));
        //the above is similar to :  verify(daoMock, times(1)).save(any(Customer.class));

        //verify that the exists method is invoked one time
        verify(daoMock, times(1)).exists(anyString());

        //verify that the delete method has never been  invoked

        verify(daoMock, never()).delete(any(Customer.class));
    }

}


Capture Arguments

Another cool feature is the ArgumentCaptor, which allows us to capture any arguments passed into the mocked or spied methods.

Mockito.ArgumentCaptor:

package com.service;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import com.dao.CustomerDao;
import com.entity.Customer;

public class CustomerServiceTest {

    @Mock
    private CustomerDao doaMock;

    @InjectMocks
    private CustomerService service;

    @Captor
    private ArgumentCaptor<Customer> customerArgument;

    public CustomerServiceTest() {

        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testRegister() {

        //Requirement: we want to register a new customer. Every new customer should be assigned a random token before saving in the database.

        service.register(new Customer());

        //captures the argument which was passed in to save method.
        verify(doaMock).save(customerArgument.capture());

        //make sure a token is assigned by the register method before saving.
        assertThat(customerArgument.getValue().getToken(), is(notNullValue()));
    }
}


I Spy: Spying With Mockito

Why spy?

  • Sometimes we need to call real methods of a dependency but still want to verify or track interactions with that dependency. This is where we would use a spy.
  • When a field is annotated with @Spy, Mockito will create a wrapper around an actual instance of that object and, therefore, we can call a real implementation and also verify interactions at the same time.
  • Some of the behavior of a spy could be mocked if needed.
  • In the example below, the dependency behavior is not mocked, but its interactions are verified.

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

public class CustomerServiceTestV2 {

    @Spy
    private CustomerDaoImpl daoSpy;

    @InjectMocks
    private CustomerService service;

    @Before
    public void setUp() throws Exception {

        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() {

        Customer customer = new Customer();

        assertThat(service.addCustomer(customer), is(false));

        verify(daoSpy).save(any(Customer.class));

        verify(daoSpy, times(1)).exists(anyString());

        verify(daoSpy, never()).delete(any(Customer.class));
    }

}


Head over here to get the example source code given in this tutorial.

That’s it on this post! Please check out the below websites for more cool features, best practices, and guidelines on Mockito.

  • Official Mockito website

  • Mockito Main reference documentation

  • Wiki page

Mockito unit test Dependency

Published at DZone with permission of Dilini Rajapaksha. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How to Migrate From JUnit 4 to JUnit 5 Step by Step
  • Understanding the Two Schools of Unit Testing
  • IntelliJ Integration for Mockito
  • The Most Popular Technologies for Java Microservices Right Now

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!