El mock tautológico
Este test pasa aunque borres todo tu código. Esa es la firma de un mock tautológico: el mock devuelve exactamente el valor que el test luego afirma, así que el mock responde su propia pregunta. La suite sigue en verde, la cobertura se ve bien, y el código de producción nunca se ejecuta. Los asistentes de IA para programar generan este patrón todo el tiempo — cuando les pides "agrega un test", hacen stub de cada dependencia y afirman el stub — así que necesitas una forma rápida de detectarlo.
Anatomía de un test que no prueba nada
def test_get_total(mocker):
mocker.patch("cart.compute_total", return_value=42)
assert get_total(cart) == 42 # asserts the mock, not the code
Sigue el dato: el valor 42 entra por el mock y sale por la aserción sin tocar una sola línea que escribiste. compute_total podría contener un bug, una excepción o nada en absoluto — el test no puede notarlo. En el vocabulario de testing de Google, estos son primos cercanos de los change-detector tests: tests que reflejan la implementación, se rompen con cada refactor y nunca atrapan un defecto real.
El detector de 10 segundos
Una sola pregunta expone casi todo mock tautológico: ¿este test podría fallar? En concreto:
- Prueba de borrar el cuerpo. Reemplaza la función bajo prueba con
return 42(o comenta su cuerpo si un mock provee su salida). ¿Sigue en verde? El test no verifica nada. - Prueba de rojo primero. Un test nuevo legítimo falla antes de que escribas el código — ese es el paso rojo de rojo-verde-refactor. Si un test recién escrito pasa a la primera, no está probando nada.
- Rastrea el valor afirmado. Si el valor esperado aparece dos veces en el archivo de test — una en un
return_value, otra en unassert— y en el medio ningún código de producción lo transforma, tienes una tautología.
Qué usar en su lugar
| Situación | Usa | Por qué |
|---|---|---|
| Lógica pura, dependencias baratas | La implementación real | Máxima fidelidad; los refactors no rompen los tests |
| Dependencia lenta/externa (BD, API) | Un fake en memoria con comportamiento funcional | Ejercita rutas de llamada reales sin la red |
| Debes verificar que ocurrió una interacción | Un mock — afirmando la llamada, no un valor en eco | La verificación de comportamiento es lo único que los mocks hacen bien |
| Vas a mockear de todas formas | autospec=True / spec | El mock rechaza llamadas que la API real rechazaría |
La distinción de Martin Fowler es la clave: un fake tiene una implementación funcional (un repositorio en memoria que realmente guarda y recupera), mientras que un stub entrega respuestas enlatadas. Los fakes pueden equivocarse de maneras interesantes — que es justo lo que hace significativos a los tests contra ellos. El equipo de testing de Google lleva una década empujando la misma línea: prefiere implementaciones reales, luego fakes, y mockea solo lo que no puedes ejecutar.
Movidas de usuario avanzado
- Autospec a todo lo que mockees.
unittest.mock.patch(..., autospec=True)copia la firma real, así quemock_fn("wrong", "args")lanzaTypeErroren vez de tener éxito en silencio. UnMock()pelado acepta cualquier llamada con cualquier argumento — el ambiente perfecto para tests que no pueden fallar. - Mantén un fake por frontera, en código cercano a producción. Un
InMemoryOrderRepocompartido usado por 40 tests se mantiene y se confía; 40 llamadas ad-hoc amocker.patchson 40 tautologías en espera. - Testea con mutaciones a los sospechosos. Corre una herramienta de mutación (o muta a mano: invierte un operador, corre un límite por uno) en módulos con mocking pesado. Los mutantes que sobreviven son tests que afirman mocks, no lógica.
- Condiciona los tests generados por IA al paso rojo. Cuando un asistente escribe tests para código existente, pídele que también muestre cada test fallando contra una implementación vaciada. Si no puede producir un fallo, rechaza el test.
Recursos
- Mocks Aren't Stubs — Martin Fowler
- Testing on the Toilet: Don't Overuse Mocks — Google Testing Blog
- Change-Detector Tests Considered Harmful — Google Testing Blog
- Increase Test Fidelity By Avoiding Mocks — Google Testing Blog
- unittest.mock —
return_value,specyautospec(documentación de Python)
¿Construyendo una funcionalidad con IA? Yeda AI diseña, audita y entrega sistemas LLM de producción.