对间谍 (Spy) 进行存根 (Stubbing) 处理和异常处理
在这一步中,你将学习如何对间谍 (Spy) 进行存根 (Stubbing) 处理以覆盖其默认行为,以及如何处理使用 Mockito 时可能出现的异常。
对间谍 (Spy) 进行存根 (Stubbing) 处理
间谍 (Spy) 默认使用真实对象的方法,但有时为了测试目的,你需要改变这种行为。这被称为对间谍 (Spy) 进行“存根 (Stubbing)”处理。下面添加一个测试方法来演示如何对间谍 (Spy) 进行存根 (Stubbing) 处理:
@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);
}
关于存根 (Stubbing) 的重要注意事项
在对间谍 (Spy) 的方法进行存根 (Stubbing) 处理时,建议使用 doReturn()
、doThrow()
、doAnswer()
等方法,而不是 when()
。这是因为对于间谍 (Spy),when().thenReturn()
语法在存根 (Stubbing) 过程中可能会调用真实方法,从而导致意外的副作用。
例如:
// 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
处理 NotAMockException
如果你尝试在普通对象(不是模拟对象 (Mock) 或间谍 (Spy))上使用 Mockito 的验证方法,就会抛出 NotAMockException
。下面添加一个测试方法来演示这个异常:
@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
代码应该能无错误地编译。在这一步中,你学习了如何对间谍 (Spy) 的方法进行存根 (Stubbing) 处理以覆盖其默认行为,以及如何处理在普通对象上使用验证方法时出现的 NotAMockException
。
下一步,你将比较模拟对象 (Mock) 和间谍 (Spy),以了解它们的关键区别。