Las pruebas unitarias son una parte esencial del desarrollo de software, ya que permiten verificar que los componentes individuales de una aplicación funcionen correctamente. Dos técnicas comunes utilizadas en las pruebas unitarias son los mocks y los fakes.
En esta nueva guía práctica, exploraremos en detalle qué son los mocks y los fakes, sus diferencias, y cómo utilizarlos en pruebas unitarias con ejemplos prácticos.
¿Qué es un Mock en Pruebas Unitarias?
Un mock es un objeto simulado que reemplaza a un componente real en una prueba unitaria. Los mocks se utilizan para probar la interacción entre objetos, permitiendo al tester verificar si los métodos esperados se llaman con los parámetros correctos. Los mocks son particularmente útiles cuando el objeto real es difícil de configurar, lento, o tiene efectos secundarios no deseados.
Características de los Mocks
- Controlado y Predecible: Los mocks permiten controlar el comportamiento de los objetos simulados, haciendo que las pruebas sean más predecibles.
- Verificación de Interacciones: Los mocks se utilizan para verificar si ciertos métodos se llaman durante la ejecución de la prueba.
- Independencia del Código Externo: Los mocks ayudan a aislar el código bajo prueba de las dependencias externas.
Ejemplo de Uso de Mocks
Supongamos que estamos probando una clase OrderService
que depende de un PaymentGateway
. Queremos verificar que OrderService
llame al método processPayment
de PaymentGateway
.
![Métodos de Clase en Python: Qué Son y Cómo Usarlos](https://aiweblearning.com/wp-content/uploads/2024/07/metodos-de-clase-python-150x150.jpg)
public class OrderService {
private PaymentGateway paymentGateway;
public OrderService(PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
public boolean placeOrder(Order order) {
return paymentGateway.processPayment(order);
}
}
// Prueba unitaria usando mock
public class OrderServiceTest {
@Test
public void testPlaceOrder() {
// Crear un mock de PaymentGateway
PaymentGateway mockPaymentGateway = mock(PaymentGateway.class);
// Configurar el comportamiento del mock
when(mockPaymentGateway.processPayment(any(Order.class))).thenReturn(true);
// Crear una instancia de OrderService con el mock
OrderService orderService = new OrderService(mockPaymentGateway);
// Ejecutar el método bajo prueba
boolean result = orderService.placeOrder(new Order());
// Verificar que el método processPayment fue llamado
verify(mockPaymentGateway).processPayment(any(Order.class));
assertTrue(result);
}
}
En este ejemplo, usamos un mock de PaymentGateway
para verificar que el método processPayment
se llame cuando placeOrder
se ejecute.
¿Qué es un Fake en Pruebas Unitarias?
Un fake es una implementación simplificada pero funcional de un componente real. A diferencia de los mocks, los fakes contienen una lógica interna que simula el comportamiento del objeto real, pero de una manera más controlada y predecible. Los fakes son útiles para reemplazar dependencias que son lentas, difíciles de configurar, o tienen efectos secundarios.
Características de los Fakes
- Implementación Funcional: Los fakes tienen una implementación funcional que simula el comportamiento del componente real.
- Simplificación: Los fakes suelen ser más simples que los objetos reales, lo que los hace más rápidos y fáciles de usar en pruebas.
- Persistencia Temporal: Algunos fakes pueden incluir persistencia temporal para simular bases de datos u otros sistemas externos.
Ejemplo de Uso de Fakes
Supongamos que estamos probando una clase UserService
que depende de un UserRepository
. Creamos un fake de UserRepository
que almacena usuarios en memoria.
public class UserService {
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void addUser(User user) {
userRepository.save(user);
}
public User getUser(String id) {
return userRepository.findById(id);
}
}
// Fake de UserRepository
public class FakeUserRepository implements UserRepository {
private Map<String, User> users = new HashMap<>();
@Override
public void save(User user) {
users.put(user.getId(), user);
}
@Override
public User findById(String id) {
return users.get(id);
}
}
// Prueba unitaria usando fake
public class UserServiceTest {
@Test
public void testAddAndRetrieveUser() {
// Crear un fake de UserRepository
FakeUserRepository fakeUserRepository = new FakeUserRepository();
// Crear una instancia de UserService con el fake
UserService userService = new UserService(fakeUserRepository);
// Crear un usuario y agregarlo
User user = new User("1", "John Doe");
userService.addUser(user);
// Recuperar el usuario y verificar los detalles
User retrievedUser = userService.getUser("1");
assertEquals("John Doe", retrievedUser.getName());
}
}
En este ejemplo, usamos un fake de UserRepository
para almacenar y recuperar usuarios en memoria durante la prueba.
Diferencias entre Mocks y Fakes
Propósito
- Mocks: Se utilizan principalmente para verificar interacciones entre objetos.
- Fakes: Se utilizan para reemplazar dependencias con implementaciones simplificadas.
Implementación
- Mocks: No tienen lógica interna propia, sino que simulan comportamientos específicos.
- Fakes: Tienen una lógica interna funcional que imita el comportamiento del componente real.
Uso
- Mocks: Ideales para pruebas donde es crucial verificar que ciertos métodos se llamen.
- Fakes: Ideales para pruebas que necesitan una implementación funcional y rápida de dependencias externas.
Tanto los mocks como los fakes son herramientas esenciales en el arsenal de un desarrollador para escribir pruebas unitarias efectivas. Los mocks permiten verificar interacciones específicas, mientras que los fakes proporcionan implementaciones simplificadas de dependencias. Al comprender y utilizar estas técnicas adecuadamente, los desarrolladores pueden crear pruebas más robustas, confiables y eficientes, mejorando la calidad del software y reduciendo el tiempo de desarrollo y mantenimiento.
También te puede interesar![Cómo comentar en Java](https://aiweblearning.com/wp-content/uploads/2024/07/comentarios-en-java-150x150.jpg)