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
- Introduction
spy
Method Syntax- Examples
- Basic Usage
- Stubbing a Method
- Verifying Interactions with a Spy
- Real-World Use Case
- 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.