En este tema, aprenderemos cómo verificar interacciones con objetos mock en JUnit utilizando Mockito. Verificar interacciones es crucial para asegurarse de que los métodos de los mocks se llamen con los argumentos correctos y en el orden esperado. Esto es especialmente útil en pruebas unitarias donde queremos asegurarnos de que nuestro código interactúa correctamente con sus dependencias.
Conceptos Clave
- Mocks: Objetos simulados que imitan el comportamiento de objetos reales en un entorno controlado.
- Verificación de Interacciones: Proceso de comprobar que los métodos de los mocks se llamaron con los argumentos correctos y en el orden esperado.
Configuración Inicial
Antes de comenzar, asegúrate de tener las siguientes dependencias en tu archivo pom.xml
si estás usando Maven:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>3.11.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.7.2</version> <scope>test</scope> </dependency>
Ejemplo Práctico
Vamos a crear un ejemplo práctico para ilustrar cómo verificar interacciones con Mockito.
Paso 1: Crear las Clases a Probar
Supongamos que tenemos una clase UserService
que depende de una clase UserRepository
.
public class UserService { private UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public void addUser(String user) { userRepository.save(user); } }
Y la interfaz UserRepository
:
Paso 2: Crear el Test
Ahora, vamos a crear un test para UserService
donde verificaremos que el método save
de UserRepository
se llama correctamente.
import static org.mockito.Mockito.*; import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class UserServiceTest { @Test public void testAddUser() { // Crear el mock de UserRepository UserRepository mockRepository = Mockito.mock(UserRepository.class); // Crear una instancia de UserService con el mock UserService userService = new UserService(mockRepository); // Llamar al método addUser userService.addUser("John Doe"); // Verificar que el método save se llamó con el argumento "John Doe" verify(mockRepository).save("John Doe"); } }
Explicación del Código
-
Crear el Mock:
UserRepository mockRepository = Mockito.mock(UserRepository.class);
- Creamos un mock de
UserRepository
usando Mockito.
- Creamos un mock de
-
Inyectar el Mock:
UserService userService = new UserService(mockRepository);
- Inyectamos el mock en una instancia de
UserService
.
- Inyectamos el mock en una instancia de
-
Llamar al Método:
userService.addUser("John Doe");
- Llamamos al método
addUser
deUserService
.
- Llamamos al método
-
Verificar la Interacción:
verify(mockRepository).save("John Doe");
- Verificamos que el método
save
deUserRepository
se llamó con el argumento "John Doe".
- Verificamos que el método
Verificaciones Adicionales
Mockito ofrece varias formas de verificar interacciones adicionales:
Verificar Número de Llamadas
Podemos verificar cuántas veces se llamó un método:
Verificar que Nunca se Llamó
Podemos verificar que un método nunca se llamó:
Verificar Orden de Llamadas
Podemos verificar el orden en que se llamaron los métodos:
InOrder inOrder = inOrder(mockRepository); inOrder.verify(mockRepository).save("John Doe"); inOrder.verify(mockRepository).notifyUser("John Doe");
Ejercicio Práctico
Ejercicio
Crea una clase OrderService
que dependa de una interfaz OrderRepository
. Implementa un método placeOrder
en OrderService
que llame a saveOrder
en OrderRepository
. Escribe un test para verificar que saveOrder
se llama correctamente.
Solución
Clases a Probar
public class OrderService { private OrderRepository orderRepository; public OrderService(OrderRepository orderRepository) { this.orderRepository = orderRepository; } public void placeOrder(String order) { orderRepository.saveOrder(order); } } public interface OrderRepository { void saveOrder(String order); }
Test
import static org.mockito.Mockito.*; import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class OrderServiceTest { @Test public void testPlaceOrder() { // Crear el mock de OrderRepository OrderRepository mockRepository = Mockito.mock(OrderRepository.class); // Crear una instancia de OrderService con el mock OrderService orderService = new OrderService(mockRepository); // Llamar al método placeOrder orderService.placeOrder("Order123"); // Verificar que el método saveOrder se llamó con el argumento "Order123" verify(mockRepository).saveOrder("Order123"); } }
Conclusión
En esta sección, hemos aprendido cómo verificar interacciones con objetos mock en JUnit utilizando Mockito. La verificación de interacciones es una herramienta poderosa para asegurarse de que nuestro código interactúa correctamente con sus dependencias. Hemos cubierto los conceptos básicos y algunos ejemplos prácticos, así como ejercicios para reforzar el aprendizaje. En el siguiente módulo, exploraremos características avanzadas de JUnit.
Curso de JUnit
Módulo 1: Introducción a JUnit
Módulo 2: Anotaciones Básicas de JUnit
- Entendiendo @Test
- Usando @Before y @After
- Usando @BeforeClass y @AfterClass
- Ignorando Tests con @Ignore
Módulo 3: Aserciones en JUnit
Módulo 4: Tests Parametrizados
- Introducción a los Tests Parametrizados
- Creando Tests Parametrizados
- Usando @ParameterizedTest
- Tests Parametrizados Personalizados
Módulo 5: Suites de Tests
Módulo 6: Mocking con JUnit
Módulo 7: Características Avanzadas de JUnit
Módulo 8: Mejores Prácticas y Consejos
- Escribiendo Tests Efectivos
- Organizando el Código de Tests
- Desarrollo Guiado por Tests (TDD)
- Integración Continua con JUnit