Mockito spy Method

The spy method in Mockito is used to create spy objects. A spy is a partial mock where you can stub some methods to behave differently while leaving others to call the real methods of the object. This is useful when you want to test a real object but override certain methods for testing purposes.

Table of Contents

  1. Introduction
  2. spy Method Syntax
  3. Examples
    • Basic Usage
    • Stubbing a Method
    • Verifying Interactions with a Spy
  4. Real-World Use Case
  5. Conclusion

Introduction

Mockito is a popular library in Java for creating mock and spy objects. The spy method allows you to create a spy of a real object, which means you can override specific methods while keeping the original behavior for others. This is helpful for testing classes with complex dependencies or behavior.

spy Method Syntax

Creating a Spy from a Class

static <T> T spy(Class<T> classToSpy)

Creates a spy instance of the given class.

Creating a Spy from an Object

static <T> T spy(T object)

Creates a spy of the given real object.

Creating a Spy from Multiple Objects

static <T> T spy(T... reified)

Creates spies for multiple real objects.

Examples

Basic Usage

Create a spy instance of a class.

import static org.mockito.Mockito.spy;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class BasicSpyTest {
    @Test
    void testSpy() {
        UserService userService = spy(UserService.class);
        String details = userService.getUserDetails("123");
        assertEquals("Real user details for 123", details);
    }
}

class UserService {
    public String getUserDetails(String userId) {
        return "Real user details for " + userId;
    }
}

Stubbing a Method

Stub a method of a spy to change its behavior.

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.doReturn;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class StubbingSpyTest {
    @Test
    void testStubMethod() {
        UserService userService = spy(UserService.class);
        doReturn("Stubbed user details for 123").when(userService).getUserDetails("123");
        String details = userService.getUserDetails("123");
        assertEquals("Stubbed user details for 123", details);
    }
}

class UserService {
    public String getUserDetails(String userId) {
        return "Real user details for " + userId;
    }
}

Verifying Interactions with a Spy

Verify that specific methods were called on the spy object.

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;

public class VerifyingSpyTest {
    @Test
    void testVerifyInteractions() {
        UserService userService = spy(UserService.class);
        userService.getUserDetails("123");
        verify(userService).getUserDetails("123");
    }
}

class UserService {
    public String getUserDetails(String userId) {
        return "Real user details for " + userId;
    }
}

Real-World Use Case

Testing a Service with Dependency

In a real-world scenario, you might have a UserService class that depends on a UserRepository. Using Mockito, you can create a spy of the UserService to test it while stubbing certain methods.

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class User {
    private String id;
    private String name;

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

    public String getName() {
        return name;
    }
}

interface UserRepository {
    User findUserById(String id);
}

class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public String getUserName(String userId) {
        User user = userRepository.findUserById(userId);
        return user != null ? user.getName() : null;
    }

    public String getUserDetails(String userId) {
        return "Real user details for " + userId;
    }
}

public class UserServiceTest {
    @Test
    void testGetUserName() {
        // Given
        UserRepository mockUserRepository = spy(UserRepository.class);
        UserService userService = spy(new UserService(mockUserRepository));
        doReturn(new User("123", "John Doe")).when(mockUserRepository).findUserById("123");
        
        // When
        String userName = userService.getUserName("123");
        
        // Then
        assertEquals("John Doe", userName);
        verify(mockUserRepository).findUserById("123");
    }
}

In this example, the UserServiceTest class uses Mockito’s spy method to create a spy of the UserService and UserRepository. The test then stubs the findUserById method of the UserRepository, calls the method under test, and verifies the behavior and interactions.

Conclusion

The spy method in Mockito is used for creating spy objects that allow partial mocking. By using spy, you can test real objects while overriding specific methods for testing purposes. This helps ensure that your tests are focused on the behavior you want to verify without being affected by other methods.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top