🧪 Formato de pruebas Unitarias
📋 Información General
| Campo | Valor | Campo | Valor |
|---|---|---|---|
| Proyecto: [Nombre del Proyecto] | Código Proyecto: [codigo] | ||
| Sprint / Release: | [Sprint 03 – Comercial] | Versión del Sistema: | [1.0] |
| Fecha de elaboración: | [dd/mm/aaaa] | DEV Responsable: | [Nombre del DEV] |
| **✅ Identificador / Nombre del test: **UT-ID#US-001 `debe_crear_usuario_correctamente_cuando_cliente_es_premium` | |||
| Objetivo: Validar que el sistema cree correctamente un usuario cuando recibe datos válidos. | |||
| Tipo de Prueba: | [Unitaria / Mock de repositorio / Sin acceso real a BD] |
✅ Identificador / Nombre del test:
UT-ID#US-001 `debe_crear_usuario_correctamente_cuando_cliente_es_premium`
Objetivo: Validar que el sistema cree correctamente un usuario cuando recibe datos válidos.
Tipo de Prueba:
[Unitaria / Mock de repositorio / Sin acceso real a BD]
🎯 Vista rápida de la prueba
⚙️ Método/Clase bajo prueba
UserService.createUser()
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
public User register(String name, String email, String password) {
if (userRepository.existsByEmail(email)) {
throw new IllegalArgumentException("Email already registered");
}
String encodedPassword = passwordEncoder.encode(password);
User user = new User(name, email, encodedPassword);
return userRepository.save(user);
}
}
🔐 Precondiciones
- Base de datos accesible
- Email no registrado previamente
📥 Datos de entrada
{
"name": "Juan",
"email": "juan@test.com",
"password": "123456"
}
🎯 Resultado esperado
- Usuario persistido
- ID generado
- No se lanza excepción
✅ Resultado esperado
🧪 Implementación de la prueba unitaria
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@Mock
private PasswordEncoder passwordEncoder;
@InjectMocks
private UserService userService;
private final String NAME = "Juan";
private final String EMAIL = "juan@test.com";
private final String PASSWORD = "123456";
@Test
@DisplayName("register_conDatosValidos_guardaUsuarioCorrectamente")
void register_conDatosValidos_guardaUsuarioCorrectamente() {
// Arrange
when(userRepository.existsByEmail(EMAIL)).thenReturn(false);
when(passwordEncoder.encode(PASSWORD)).thenReturn("encodedPassword");
User savedUser = new User(NAME, EMAIL, "encodedPassword");
when(userRepository.save(any(User.class))).thenReturn(savedUser);
// Act
User result = userService.register(NAME, EMAIL, PASSWORD);
// Assert
assertNotNull(result);
assertEquals(EMAIL, result.getEmail());
assertEquals("encodedPassword", result.getPassword());
verify(userRepository).existsByEmail(EMAIL);
verify(passwordEncoder).encode(PASSWORD);
verify(userRepository).save(any(User.class));
}
@Test
@DisplayName("register_conEmailDuplicado_lanzaExcepcion")
void register_conEmailDuplicado_lanzaExcepcion() {
// Arrange
when(userRepository.existsByEmail(EMAIL)).thenReturn(true);
// Act & Assert
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> userService.register(NAME, EMAIL, PASSWORD)
);
assertEquals("Email already registered", exception.getMessage());
verify(userRepository, never()).save(any());
verify(passwordEncoder, never()).encode(any());
}
}
🧠 Flujo Arrange → Act → Assert
🔀 Escenarios cubiertos por el ejemplo
📊 Cobertura asociada
- Línea:
- Rama:
- Caso límite cubierto
📈 Cobertura
📦 Dependencias
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.8</version>
<scope>test</scope>
</dependency>
✅ NOTA: Buenas prácticas que se deben de incluir en las pruebas
Unitarias
Me enfoco en:
- ✅ Casos felices
- ✅ Casos límite (boundary values)
- ✅ Casos negativos
- ✅ Manejo de excepciones
- ✅ Comportamiento ante null o valores vacíos
- ✅ Verificación de efectos secundarios
- ✅ Independencia del test
- ✅ Tests rápidos y determinísticos
- ✅Métricas de cobertura mínima (ej: 80%+)
- ✅Reportes automatizados (Sonar, CI)
- ✅Convenciones obligatorias de naming
- ✅Tests parametrizados para reducir duplicación :::
🎮 Mapa visual de buenas prácticas
🚀 Ciclo visual completo