Table of contents
1.
Introduction
2.
Mocking Interface With Mockito
2.1.
Program
2.2.
Program
2.3.
Program
2.4.
Output
3.
Return Default Values for Optional and Stream
3.1.
Program
3.2.
Program
3.3.
Program
3.4.
Output
4.
Lambda Expressions
4.1.
Lambda With ArgumentMatcher
4.1.1.
Program
4.1.2.
Output
4.2.
Lambda With Custom Answer
4.2.1.
Program
4.2.2.
Output
5.
FAQs
6.
Key Takeaways
Last Updated: Mar 27, 2024
Easy

Mockito With Java 8

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Java 8 is a convenient release of one of the most popular development platforms. Java 8 introduces a wide range of new and valuable features, like lambda and streams. The Mockito mocking framework, which we use to perform unit testing of Java applications, leveraged these features and innovations in Java 8.

We will explore these new Java 8 features and their implementation in the Mockito framework through explanations and examples in this article.

Mocking Interface With Mockito

Java 8 introduces writing method implementations in your interfaces. This feature is not supported by Mockito version 1 because it does not allow you to ask Mockito to real methods from interfaces and throws an error.

So to mock interface with Mockito in Java 8, you can change the Mockito version in your maven project‘s pom.xml file. 

<dependency>
<groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>2.7.5</version>
      <scope>test</scope>
</dependency>

 

For the examples we will use in this article, we will create two Java classes, JobPosition and Person

Program

//src/main/java/com.codingninjas.testrunner/JobPosition.java
package com.codingninjas.testrunner;


public class JobPosition {
    private String title;
    
    public JobPosition() {}
    
    public JobPosition(String title) {
        super();
        this.title = title;
    }


    public String getTitle() {
        return title;
    }


    public void setTitle(String title) {
        this.title = title;
    }
}
Program
//src/main/java/com.codingninjas.testrunner/Person.java
package com.codingninjas.testrunner;


public class Person {
    private String name;
    private JobPosition currentJobPosition;
    
    public Person() {}
    
    public Person(String name) {
        this.name = name;
    }


    public JobPosition getCurrentJobPosition() {
        return currentJobPosition;
    }


    public void setCurrentJobPosition(JobPosition currentJobPosition) {
        this.currentJobPosition = currentJobPosition;
    }


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }
}
You can also try this code with Online Java Compiler
Run Code

Now we can create an interface, JobService, with two method declarations. One with the traditional method signature and one with the new default method of Java 8.

Program

//src/main/java/com.codingninjas.testrunner/JobService.java
package com.codingninjas.testrunner;


import java.util.Optional;
import java.util.stream.Stream;


public interface JobService {
 
    Optional<JobPosition> findCurrentJobPosition(Person person);
    
    default boolean assignJobPosition(Person person, JobPosition jobPosition) {
        if(!findCurrentJobPosition(person).isPresent()) {
            person.setCurrentJobPosition(jobPosition);
            
            return true;
        } else {
            return false;
        }
    }
    
    Stream<JobPosition> listJobs(Person person);
}
You can also try this code with Online Java Compiler
Run Code

It is worth noting that the default method assignJobPosition() has a call to the unimplemented findCurrentJobPosition() method.

Now we can test our implementation by creating a mocked version of the JobService and telling Mockito to return a known value from our unimplemented method call and call the real method after calling the assignJobPosition().

Program

//src/test/java/com.codingninjas.testrunner/JobServiceUnitTest.java
package com.codingninjas.testrunner;


import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;


import java.util.Optional;


import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.when;


@RunWith(MockitoJUnitRunner.class)
public class JobServiceUnitTest {
    @Mock
    private JobService jobService;


    @Test
    public void givenDefaultMethod_whenCallRealMethod_thenNoExceptionIsRaised() {
        Person person = new Person();


        when(jobService.findCurrentJobPosition(person)).thenReturn(Optional.of(new JobPosition()));
        doCallRealMethod().when(jobService).assignJobPosition(Mockito.any(Person.class), Mockito.any(JobPosition.class));


        assertFalse(jobService.assignJobPosition(person, new JobPosition()));
    }
}
You can also try this code with Online Java Compiler
Run Code

Output

Return Default Values for Optional and Stream

Optional and Stream are other key features introduced in Java 8. The Optional class is a container object that you can use to contain not-null objects, and you can use the Stream to process collections of objects. A similarity between these two classes is that they both have a particular object type representing an empty object. This empty object makes it easier for us to avoid the NullPointerException we constantly encounter.

For our example, to return default values for Optional, we are going to create a service(UnemploymentService) that injects the JobService from the previous program and has a method that calls findCurrentJobPosition() and then implements that service interface in a class(UnemploymenyServiceImp).

And in the same class(UnemploymenyServiceImp), we can also mock Stream, which will show similar behavior. 

Here we will use the listJobs method that we included in our JobService interface program above. This method returns a stream that represents all the job positions of the employee.

{
..
Stream<JobPosition> listJobs(Person person);
..
}
You can also try this code with Online Java Compiler
Run Code

We will use this method in a new method in our UnemploymenyServiceImp class that will query if a person is working on a job matching a given search string. 

Now we have the program for our interface and class.

Program

//src/main/java/com.codingninjas.testrunner/UnemploymentService.java
package com.codingninjas.testrunner;


import java.util.Optional;


public interface UnemploymentService {


    boolean personIsEntitledToUnemploymentSupport(Person person);


    Optional<JobPosition> searchJob(Person person, String searchString); 


}
You can also try this code with Online Java Compiler
Run Code

Program

//src/main/java/com.codingninjas.testrunner/UnemploymentService.java
package com.codingninjas.testrunner;


import java.util.Optional;
import java.util.stream.Stream;


public class UnemploymentServiceImpl implements UnemploymentService {
    private final JobService jobService;
    
    public UnemploymentServiceImpl(JobService jobService) {
        this.jobService = jobService;
    }


    @Override
    public boolean personIsEntitledToUnemploymentSupport(Person person) {
        Optional<JobPosition> optional = jobService.findCurrentJobPosition(person);
        
        return !optional.isPresent();
    }
    @Override
    public Optional<JobPosition> searchJob(Person person, String searchString) {
        Stream<JobPosition> stream = jobService.listJobs(person);
        
        return stream.filter((j) -> j.getTitle().contains(searchString)).findFirst();
    }
}
You can also try this code with Online Java Compiler
Run Code

We can test both the returns with tests that check if a person has no current job position(forcing findCurrentJobPosition() to return an empty Optional). And if the person has not had any work at any jobs yet(listJobs() returns an empty Stream) using Mockito version 2.

Program

//src/test/java/com.codingninjas.testrunner/UnemploymentServiceImpUnitTest.java
package com.codingninjas.testrunner;

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.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;


@RunWith(MockitoJUnitRunner.class)
public class UnemploymentServiceImplUnitTest {
    @Mock
    private JobService jobService;


    @InjectMocks
    private UnemploymentServiceImpl unemploymentService;


    @Test
    public void givenReturnIsOfTypeOptional_whenDefaultValueIsReturned_thenValueIsEmpty() {
        Person person = new Person();


        assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(person));
    }
    
    @Test
    public void givenReturnIsOfTypeStream_whenDefaultValueIsReturned_thenValueIsEmpty() {
        Person person = new Person();


        assertFalse(unemploymentService.searchJob(person, "").isPresent());
    }
}
You can also try this code with Online Java Compiler
Run Code

Output

Lambda Expressions

Lambda Expressions in Java 8 allow you to make more compact and readable statements. ArgumentMatchers and Custom Answers are two good examples of simplicity introduced by lambda expressions while using Mockito version 2. 

Lambda With ArgumentMatcher

The Lambda expressions feature in Java 8 allows you to replace the inner class you would have to create before java 8 to implement ArgumentMatcher with a simple lambda expression.

Program

////src/test/java/com.codingninjas.testrunner/ArgumentMatcherWithLambdaUnitTest.java
package com.codingninjas.testrunner;


import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;


import java.util.Optional;


import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;


@RunWith(MockitoJUnitRunner.class)
public class ArgumentMatcherWithLambdaUnitTest {


    @InjectMocks
    private UnemploymentServiceImpl unemploymentService;
    
    @Mock
    private JobService jobService;


    @Test
    public void whenPersonWithJob_thenIsNotEntitled() {
        Person peter = new Person("Peter");
        Person linda = new Person("Linda");
        
        JobPosition teacher = new JobPosition("Teacher");


        when(jobService.findCurrentJobPosition(
                ArgumentMatchers.argThat((p) -> p.getName().equals("Peter")))
             ).thenReturn(Optional.of(teacher));
        
        assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(linda));
        assertFalse(unemploymentService.personIsEntitledToUnemploymentSupport(peter));
    }
}
You can also try this code with Online Java Compiler
Run Code

Output

Lambda With Custom Answer

Combining lambda expressions with the Custom Answer of Mockito will give you a similar result. Using lambda expression allows you to write all the mock behavior inline.

In the example below, we want to simulate calls to the listJobs() method to make it return a Stream that contains a single JobPosition if the person's name is "Peter". Otherwise, return an empty Stream. You would have to create an anonymous or inner class that implements the Answer interface without lambda expression. But here, we do not need a PersonAnswer inner class.

Program

////src/test/java/com.codingninjas.testrunner/CustomAnswerWithLambdaUnitTest.java
package com.codingninjas.testrunner;


import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;


import java.util.stream.Stream;


import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;


@RunWith(MockitoJUnitRunner.class)
public class CustomAnswerWithLambdaUnitTest {


    @InjectMocks
    private UnemploymentServiceImpl unemploymentService;


    @Mock
    private JobService jobService;


    @Test
    public void whenPersonWithJobHistory_thenSearchReturnsValue() {
        Person peter = new Person("Peter");


        assertEquals("Teacher", unemploymentService.searchJob(peter, "").get().getTitle());
    }



    @Before
    public void init() {
        when(jobService.listJobs(any(Person.class))).then((i) ->
          Stream.of(new JobPosition("Teacher"))
          .filter(p -> ((Person) i.getArgument(0)).getName().equals("Peter")));
    }
}
You can also try this code with Online Java Compiler
Run Code

Output

FAQs

1. Is Mockito part of JUnit?

Ans: Mockito is not a part of the JUnit testing framework. Mockito is a mocking framework based on java, which you can use with other testing frameworks such as JUnit and TestNG. It uses Java Reflection API internally and allows you to create objects of a service.

 

2. How do I use Mockito annotations?

Ans: To use Mockito annotations, you need to initialize them using one of these three techniques.

  1. Using @RunWith(MockitoJUnitRunner.class) at the top of the unit test class.
  2. Using MockitoAnnotations.initMocks(this) in the @Before method of the unit test class.
  3. Using MockitoJUnit.rule() to create a MockitoRule class.

 

3. What is a Mockito spy?

Ans: A Mockito spy is similar to a partial mock. You can mock a part of the object by stubbing a few methods while using real method invocations for the other part. Calling a method on a spy invokes the actual method unless you explicitly stub the method, hence the term partial mock.

 

4. What is stubbing in Mockito?

Ans: Mockito provides a when and then stubbing pattern to stub a method invocation of a mock object. The mock API invocation goes into when(), a static Mockito API method and the value we want the mock to return goes into the then() API.

Key Takeaways

This article extensively discussed Java 8 features and their implementation in the Mockito mocking framework. Through elaborate examples, we have understood Mockito's Java 8 features like mocking interfaces with Mockito, returning default values for Optional and Stream, and leveraging Lambda Expressions.

We hope this blog has helped you enhance your knowledge regarding Unit Testing in Java with Mockito and JUnit. If you would like to keep learning, check out our articles on JUnit Introduction and FeaturesJUnit Environment Setup and Framework, and Basics of Java. Do upvote our blog to help other ninjas grow. Happy Coding!

Live masterclass