import org.junit.Test;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.MockitoAnnotations;
import org.mockito.exceptions.misusing.NotAMockException;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class MockitoSpyDemo {
public static void main(String[] args) {
System.out.println("This is a Mockito Spy demonstration.");
System.out.println("To run the tests, you need to use JUnit.");
}
}
@Test
public void basicSpyExample() {
// Create a list and spy on it
List<String> realList = new ArrayList<>();
List<String> spyList = Mockito.spy(realList);
// Using the spy to add an item (the real method is called)
spyList.add("Hello");
// Verify the interaction happened
Mockito.verify(spyList).add("Hello");
// The real method was called, so the list actually has the item
assertEquals(1, spyList.size());
assertEquals("Hello", spyList.get(0));
System.out.println("Basic Spy Example - Spy List Content: " + spyList);
System.out.println("Basic Spy Example - Spy List Size: " + spyList.size());
}
コードをコンパイルして実行し、動作を確認しましょう。
cd ~/project
javac -cp lib/junit.jar:lib/mockito-core.jar:lib/byte-buddy.jar:lib/byte-buddy-agent.jar:lib/objenesis.jar:lib/hamcrest-core.jar MockitoSpyDemo.java
java -cp .:lib/junit.jar:lib/mockito-core.jar:lib/byte-buddy.jar:lib/byte-buddy-agent.jar:lib/objenesis.jar:lib/hamcrest-core.jar MockitoSpyDemo
次の出力が表示されるはずです。
This is a Mockito Spy demonstration.
To run the tests, you need to use JUnit.
@Test
public void testSpyWithMockitoSpyMethod() {
// Create an ArrayList and a spy of it
ArrayList<Integer> realList = new ArrayList<>();
ArrayList<Integer> spyList = Mockito.spy(realList);
// Adding elements to the spy (real methods are called)
spyList.add(5);
spyList.add(10);
spyList.add(15);
// Verifying interactions
Mockito.verify(spyList).add(5);
Mockito.verify(spyList).add(10);
Mockito.verify(spyList).add(15);
// Verifying that elements were actually added to the list
assertEquals(3, spyList.size());
System.out.println("Spy Method Example - Spy List Content: " + spyList);
System.out.println("Spy Method Example - Spy List Size: " + spyList.size());
}
// Declare a spy using annotation
@Spy
ArrayList<Integer> annotationSpyList = new ArrayList<>();
@Before
public void initSpies() {
// Initialize mocks and spies with annotations
MockitoAnnotations.initMocks(this);
}
@Test
public void testSpyWithAnnotation() {
// Adding elements to the spy
annotationSpyList.add(5);
annotationSpyList.add(10);
annotationSpyList.add(15);
// Verifying interactions
Mockito.verify(annotationSpyList).add(5);
Mockito.verify(annotationSpyList).add(10);
Mockito.verify(annotationSpyList).add(15);
// Verifying that elements were actually added to the list
assertEquals(3, annotationSpyList.size());
System.out.println("Annotation Spy Example - Spy List Content: " + annotationSpyList);
System.out.println("Annotation Spy Example - Spy List Size: " + annotationSpyList.size());
}
@Test
public void testStubbingSpy() {
// Create a spy of ArrayList
ArrayList<Integer> spyList = Mockito.spy(new ArrayList<>());
// Add an element
spyList.add(5);
// Verify the element was added
Mockito.verify(spyList).add(5);
// By default, contains() should return true for element 5
assertTrue(spyList.contains(5));
System.out.println("Stubbing Example - Default behavior: spyList.contains(5) = " + spyList.contains(5));
// Stub the contains() method to always return false for the value 5
Mockito.doReturn(false).when(spyList).contains(5);
// Now contains() should return false, even though the element is in the list
assertFalse(spyList.contains(5));
System.out.println("Stubbing Example - After stubbing: spyList.contains(5) = " + spyList.contains(5));
// The element is still in the list (stubbing didn't change the list content)
assertEquals(1, spyList.size());
assertEquals(Integer.valueOf(5), spyList.get(0));
System.out.println("Stubbing Example - Spy List Content: " + spyList);
}
// This might call the real get() method, causing issues if index 10 doesn't exist
Mockito.when(spyList.get(10)).thenReturn(99); // May throw IndexOutOfBoundsException
// This is the correct way to stub a spy
Mockito.doReturn(99).when(spyList).get(10); // Safe, doesn't call the real method
@Test
public void testNotAMockException() {
try {
// Create a regular ArrayList (not a mock or spy)
ArrayList<Integer> regularList = new ArrayList<>();
regularList.add(5);
// Try to verify an interaction on a regular object
Mockito.verify(regularList).add(5);
fail("Expected NotAMockException was not thrown");
} catch (NotAMockException e) {
// Expected exception
System.out.println("NotAMockException Example - Caught expected exception: " + e.getMessage());
assertTrue(e.getMessage().contains("Argument passed to verify() is not a mock"));
}
}
更新されたコードをコンパイルしましょう。
cd ~/project
javac -cp lib/junit.jar:lib/mockito-core.jar:lib/byte-buddy.jar:lib/byte-buddy-agent.jar:lib/objenesis.jar:lib/hamcrest-core.jar MockitoSpyDemo.java
@Test
public void testMockVsSpyDifference() {
// Create a mock and a spy of ArrayList
ArrayList<Integer> mockList = Mockito.mock(ArrayList.class);
ArrayList<Integer> spyList = Mockito.spy(new ArrayList<>());
// Add elements to both
mockList.add(1);
spyList.add(1);
// Verify interactions (both will pass)
Mockito.verify(mockList).add(1);
Mockito.verify(spyList).add(1);
// Check the size of both lists
System.out.println("Mock vs Spy - Mock List Size: " + mockList.size());
System.out.println("Mock vs Spy - Spy List Size: " + spyList.size());
// Mock returns default values (0 for size) unless stubbed
assertEquals(0, mockList.size());
// Spy uses real method implementation, so size is 1
assertEquals(1, spyList.size());
// Stub both to return size 100
Mockito.when(mockList.size()).thenReturn(100);
Mockito.when(spyList.size()).thenReturn(100);
// Both should now return 100 for size
assertEquals(100, mockList.size());
assertEquals(100, spyList.size());
System.out.println("Mock vs Spy (After Stubbing) - Mock List Size: " + mockList.size());
System.out.println("Mock vs Spy (After Stubbing) - Spy List Size: " + spyList.size());
}
@Test
public void testWhenToUseSpy() {
// Create a complex data object that we want to partially mock
StringBuilder builder = new StringBuilder();
StringBuilder spyBuilder = Mockito.spy(builder);
// Use the real append method
spyBuilder.append("Hello");
spyBuilder.append(" World");
// Verify the real methods were called
Mockito.verify(spyBuilder).append("Hello");
Mockito.verify(spyBuilder).append(" World");
// The real methods modified the state
assertEquals("Hello World", spyBuilder.toString());
System.out.println("When to Use Spy - Content: " + spyBuilder.toString());
// Stub the toString() method to return something else
Mockito.when(spyBuilder.toString()).thenReturn("Stubbed String");
// Now toString() returns our stubbed value
assertEquals("Stubbed String", spyBuilder.toString());
System.out.println("When to Use Spy - After Stubbing toString(): " + spyBuilder.toString());
// But other methods still work normally
spyBuilder.append("!");
Mockito.verify(spyBuilder).append("!");
// toString() still returns our stubbed value
assertEquals("Stubbed String", spyBuilder.toString());
}
更新されたコードをコンパイルしましょう。
cd ~/project
javac -cp lib/junit.jar:lib/mockito-core.jar:lib/byte-buddy.jar:lib/byte-buddy-agent.jar:lib/objenesis.jar:lib/hamcrest-core.jar MockitoSpyDemo.java