Mockito

How to use Spies in Mockito

Hello. In this tutorial, we will understand Spy in Mockito. As stubbing is now obsolete I will focus @Spy annotation in this tutorial.

1. Introduction

Mockito is a popular framework used to mock the interfaces or classes so that dummy functionality can be added during the unit testing. It is a java based library that helps simplify the test-cases development by mocking the external dependencies. In this example, we will take a look at the Spy (i.e. @Spy) in Mockito.

  • Annotation is used to spy on an existing instance
  • Helps to partially mock an object
  • Using spy on an object results in calling the real methods unless it is stubbed

In Mockito, sometimes engineers encounter NotAMockException which is most common in the case when one forgets to mock or spy on the object and tries to mock its method. E.g. the below code will throw the exception as when expects the mocked object to be passed.

Snippet

UserSrv objUndrTest = new UserSrv();
// UserSrv objUndrTest = Mockito.mock(UserSrv.class)
Mockito.when(objUndrTest.getUsers(Mockito.any())).thenReturn(Collections.emptyList());

2. Practice

Let us dive into some practice stuff from here and I am assuming that you already have the Java 1.8 or greater installed on your local machine. I am using JetBrains IntelliJ IDEA as my preferred IDE. You’re free to choose the IDE of your choice. The below pictures shows the project structure.

Fig. 1: Project structure

2.1 Setting up the pom

Add the below code to the pom file where we will specify the dependencies required for this java project.

pom.xml

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://maven.apache.org/POM/4.0.0"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <artifactId>java-mockito-spies</artifactId>
  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
    <dependency>
      <artifactId>mockito-junit-jupiter</artifactId>
      <groupId>org.mockito</groupId>
      <scope>test</scope>
      <version>4.5.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
    <dependency>
      <artifactId>mockito-core</artifactId>
      <groupId>org.mockito</groupId>
      <scope>test</scope>
      <version>4.5.1</version>
    </dependency>
  </dependencies>

  <description>Spies in mockito</description>

  <groupId>com.learning</groupId>
  <modelVersion>4.0.0</modelVersion>
  <name>Spies in mockito</name>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>

  <version>0.0.1-SNAPSHOT</version>
</project>

2.2 Creating the model class

Create a model class in the com.learning.service.model package under the src/main/java folder.

User.java

package com.learning.service.model;

import java.util.UUID;

public class User {

  final UUID id;
  final String fullName;

  public User(final UUID id, final String name) {
    this.id = id;
    this.fullName = name;
  }

  public UUID getId() {
    return id;
  }

  public String getFullName() {
    return fullName;
  }
}

2.3 Creating the setup

To understand and implement the execution of Spy we first need to create an implementation class in the com.learning.service package under the src/main/java folder. The below code helps to create a user list.

UserSrv.java

package com.learning.service;

import com.learning.service.model.User;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class UserSrv {

  public List<User> getUsers(final boolean fetch) {
    final List<User> users = new ArrayList<>();
    if (fetch) {
      System.out.println("Populating list with elements");
      for (int i = 0; i < 10; i++) {
        users.add(new User(UUID.randomUUID(), "Some name_" + i));
      }
    }
    return users;
  }
}

2.4 Creating the test class

To understand the spy’s execution we will create a test class in the com.learning.service package under the src/test/java folder.

UserSrvTest.java

package com.learning.service;

import com.learning.service.model.User;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

/*
@Spy annotation is used to spy on an existing resource. It helps to partially mock an object.
 */
@ExtendWith(MockitoExtension.class)
public class UserSrvTest {

  @Spy
  private UserSrv objUndrTest;

  @Test
  public void getUsersShouldReturnEmployeeListIfFetchIsTrue() {
    final List<User> response = objUndrTest.getUsers(true);
    Assertions.assertNotNull(response);
    Assertions.assertEquals(response.size(), 10);
  }

  @Test
  public void getUsersShouldReturnEmptyEmployeeListIfFetchIsFalse() {
    Assertions.assertEquals(objUndrTest.getUsers(false).size(), 0);
  }
}

Run the file as a java file under the JUnit framework and one can debug the execution of it. If everything goes well all the test cases should pass. As a general recommendation, there should be no or less logging while running the test cases and hence we are following the same.

That is all for this tutorial and I hope the article served you with whatever you were looking for. Happy Learning and do not forget to share!

3. Summary

In this tutorial, we discussed the practical implementation of Spy in Mockito. You can download the source code from the Downloads section.

4. Download the Project

This was a tutorial under Spy in the Mockito framework.

Download
You can download the full source code of this example here: How to use Spies in Mockito

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button