Configuración (Stubbing) de Espías y Manejo de Excepciones
En este paso, aprenderemos cómo configurar (stub) un espía (spy) para anular su comportamiento predeterminado y entenderemos cómo manejar las excepciones que pueden ocurrir al utilizar Mockito.
Configuración (Stubbing) de un Espía
Los espías utilizan los métodos de los objetos reales por defecto, pero a veces queremos cambiar este comportamiento con fines de prueba. Esto se llama "configurar (stub)" el espía. Vamos a agregar un método de prueba que demuestre cómo configurar un espía:
@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);
}
Nota importante sobre la configuración (Stubbing)
Al configurar (stub) métodos de espías, se recomienda utilizar doReturn()
, doThrow()
, doAnswer()
, etc., en lugar de when()
. Esto se debe a que con los espías, la sintaxis when().thenReturn()
puede llamar al método real durante la configuración (stubbing), lo que puede causar efectos secundarios inesperados.
Por ejemplo:
// 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
Manejo de la excepción NotAMockException
Si intentas utilizar los métodos de verificación de Mockito en un objeto normal (no un simulacro - mock o espía - spy), obtendrás una excepción NotAMockException
. Vamos a agregar un método de prueba para demostrar esta excepción:
@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"));
}
}
Compilémos nuestro código actualizado:
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
El código debería compilar sin errores. En este paso, aprendimos cómo configurar (stub) métodos de espías para anular su comportamiento predeterminado y cómo manejar la excepción NotAMockException
que se produce al utilizar métodos de verificación en objetos normales.
En el siguiente paso, compararemos simulacros (mocks) y espías (spies) para entender sus diferencias clave.