Repository navigation
Expand file tree
/
Copy pathExpMockSimulation.java
More file actions
228 lines (181 loc) · 10.4 KB
/
Copy pathExpMockSimulation.java
File metadata and controls
228 lines (181 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* Simulación del patrón Mockito con Java puro (sin dependencias externas).
*
* Demuestra:
* - Interfaz RepositorioUsuarios con buscarPorEmail(String)
* - Mock manual que registra llamadas y permite configurar respuestas
* - when().thenReturn() implementado a mano
* - verify() con conteo de invocaciones
* - ArgumentCaptor simulado
*
* Ejecutar: java -cp target/classes ExpMockSimulation
*/
public class ExpMockSimulation {
// ── Modelo ───────────────────────────────────────────────────────────────
record Usuario(Long id, String nombre, String email) {}
// ── Interfaz a mockear ───────────────────────────────────────────────────
interface RepositorioUsuarios {
Optional<Usuario> buscarPorEmail(String email);
void guardar(Usuario usuario);
void eliminar(Long id);
}
// ── Implementación del servicio bajo prueba ──────────────────────────────
static class ServicioUsuarios {
private final RepositorioUsuarios repositorio;
ServicioUsuarios(RepositorioUsuarios repositorio) {
this.repositorio = repositorio;
}
public String obtenerNombrePorEmail(String email) {
return repositorio.buscarPorEmail(email)
.map(Usuario::nombre)
.orElse("Usuario no encontrado");
}
public void registrar(String nombre, String email) {
Optional<Usuario> existente = repositorio.buscarPorEmail(email);
if (existente.isPresent()) {
throw new IllegalStateException("El email ya está registrado: " + email);
}
repositorio.guardar(new Usuario(null, nombre, email));
}
}
// ── Mock manual — simula Mockito ─────────────────────────────────────────
/**
* Mock manual de RepositorioUsuarios.
*
* Equivale a: RepositorioUsuarios mock = Mockito.mock(RepositorioUsuarios.class);
*/
static class MockRepositorioUsuarios implements RepositorioUsuarios {
// Registro de llamadas: método → lista de argumentos recibidos
private final Map<String, List<Object[]>> llamadas = new HashMap<>();
// Respuestas configuradas: clave "método:arg" → valor a devolver
private final Map<String, Object> respuestas = new HashMap<>();
// ── Configuración del mock ───────────────────────────────────────────
/**
* Simula: when(mock.buscarPorEmail("ana@email.com")).thenReturn(Optional.of(usuario));
*/
@SuppressWarnings("unchecked")
public <T> MockRepositorioUsuarios cuando(String metodo, Object argumento, T respuesta) {
String clave = metodo + ":" + argumento;
respuestas.put(clave, respuesta);
return this;
}
// ── Implementación de la interfaz ────────────────────────────────────
@Override
@SuppressWarnings("unchecked")
public Optional<Usuario> buscarPorEmail(String email) {
registrarLlamada("buscarPorEmail", email);
String clave = "buscarPorEmail:" + email;
if (respuestas.containsKey(clave)) {
return (Optional<Usuario>) respuestas.get(clave);
}
return Optional.empty(); // comportamiento por defecto — igual que Mockito
}
@Override
public void guardar(Usuario usuario) {
registrarLlamada("guardar", usuario);
}
@Override
public void eliminar(Long id) {
registrarLlamada("eliminar", id);
}
// ── Mecanismo de registro ────────────────────────────────────────────
private void registrarLlamada(String metodo, Object... args) {
llamadas.computeIfAbsent(metodo, k -> new ArrayList<>()).add(args);
}
// ── Verificaciones — simulan Mockito.verify() ────────────────────────
/**
* Simula: verify(mock).buscarPorEmail("ana@email.com");
*/
public void verify(String metodo, int veceesEsperadas) {
int vecesReales = llamadas.getOrDefault(metodo, List.of()).size();
if (vecesReales == veceesEsperadas) {
System.out.printf(" PASS verify(%s, times(%d))%n", metodo, veceesEsperadas);
} else {
System.out.printf(" FAIL verify(%s) — esperado %d invocaciones, fue %d%n",
metodo, veceesEsperadas, vecesReales);
}
}
/**
* Simula: verify(mock, never()).eliminar(any());
*/
public void verifyNever(String metodo) {
verify(metodo, 0);
}
/**
* Simula ArgumentCaptor — devuelve los argumentos capturados de la última llamada.
*/
public Object[] capturarUltimaLlamada(String metodo) {
List<Object[]> invocaciones = llamadas.getOrDefault(metodo, List.of());
if (invocaciones.isEmpty()) {
return new Object[0];
}
return invocaciones.get(invocaciones.size() - 1);
}
}
// ── Main — ejecuta los tests ─────────────────────────────────────────────
public static void main(String[] args) {
System.out.println("═══════════════════════════════════════════════");
System.out.println(" ExpMockSimulation — Patrón Mockito con Java puro");
System.out.println("═══════════════════════════════════════════════");
// ── Test 1: buscar usuario existente ────────────────────────────────
System.out.println("\n── Test 1: obtenerNombrePorEmail con usuario existente");
MockRepositorioUsuarios mock = new MockRepositorioUsuarios();
Usuario ana = new Usuario(1L, "Ana García", "ana@email.com");
// when(mock.buscarPorEmail("ana@email.com")).thenReturn(Optional.of(ana))
mock.cuando("buscarPorEmail", "ana@email.com", Optional.of(ana));
ServicioUsuarios servicio = new ServicioUsuarios(mock);
String nombre = servicio.obtenerNombrePorEmail("ana@email.com");
System.out.println(" Nombre obtenido: " + nombre);
System.out.println(" " + ("Ana García".equals(nombre) ? "PASS" : "FAIL")
+ " nombre debe ser Ana García");
// verify(mock, times(1)).buscarPorEmail(...)
mock.verify("buscarPorEmail", 1);
// ── Test 2: buscar usuario inexistente ───────────────────────────────
System.out.println("\n── Test 2: obtenerNombrePorEmail con usuario inexistente");
MockRepositorioUsuarios mock2 = new MockRepositorioUsuarios();
// sin configurar when() → devuelve Optional.empty() por defecto
ServicioUsuarios servicio2 = new ServicioUsuarios(mock2);
String resultado = servicio2.obtenerNombrePorEmail("fantasma@email.com");
System.out.println(" Resultado: " + resultado);
System.out.println(" " + ("Usuario no encontrado".equals(resultado) ? "PASS" : "FAIL")
+ " debe retornar 'Usuario no encontrado'");
mock2.verify("buscarPorEmail", 1);
// ── Test 3: registrar nuevo usuario llama a guardar ──────────────────
System.out.println("\n── Test 3: registrar usuario nuevo");
MockRepositorioUsuarios mock3 = new MockRepositorioUsuarios();
// email no existe → buscarPorEmail devuelve empty → guardar debe ser llamado
ServicioUsuarios servicio3 = new ServicioUsuarios(mock3);
servicio3.registrar("Carlos", "carlos@email.com");
mock3.verify("buscarPorEmail", 1);
mock3.verify("guardar", 1);
mock3.verifyNever("eliminar");
// ArgumentCaptor: inspeccionamos qué Usuario se pasó a guardar
Object[] args3 = mock3.capturarUltimaLlamada("guardar");
if (args3.length > 0 && args3[0] instanceof Usuario u) {
System.out.println(" ArgumentCaptor — usuario guardado: " + u);
System.out.println(" " + ("Carlos".equals(u.nombre()) ? "PASS" : "FAIL")
+ " nombre del usuario guardado debe ser Carlos");
}
// ── Test 4: registrar email duplicado lanza excepción ────────────────
System.out.println("\n── Test 4: registrar email ya existente");
MockRepositorioUsuarios mock4 = new MockRepositorioUsuarios();
mock4.cuando("buscarPorEmail", "ana@email.com", Optional.of(ana));
ServicioUsuarios servicio4 = new ServicioUsuarios(mock4);
try {
servicio4.registrar("Otro Ana", "ana@email.com");
System.out.println(" FAIL debería haber lanzado IllegalStateException");
} catch (IllegalStateException e) {
System.out.println(" PASS IllegalStateException lanzada: " + e.getMessage());
}
// guardar NO debe haberse llamado
mock4.verifyNever("guardar");
System.out.println("\n═══════════════════════════════════════════════");
System.out.println(" Fin de la simulación Mockito");
System.out.println("═══════════════════════════════════════════════");
}
}