<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Testing on Patrones — Exeal</title><link>https://patterns.exeal.com/tags/testing/</link><description>Recent content in Testing on Patrones — Exeal</description><generator>Hugo</generator><language>es-ES</language><lastBuildDate>Thu, 24 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://patterns.exeal.com/tags/testing/index.xml" rel="self" type="application/rss+xml"/><item><title>API Lite: un segundo host con infraestructura en memoria</title><link>https://patterns.exeal.com/patterns/api-lite/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/api-lite/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Un frontend (o una suite de Playwright) que depende del backend real para poder trabajar arrastra todos los problemas del backend real: hay que levantar Postgres, colas, un proveedor OIDC, a veces Hangfire o un bucket S3, y el estado se acumula entre ejecuciones. Para tocar UI esto es fricción pura — nadie necesita persistencia real para ver si un botón pinta bien. Para tests de extremo a extremo es peor: los tests dejan de ser deterministas (dependen de datos que quedaron de ejecuciones anteriores, de latencia real contra servicios externos, de que Postgres/Hangfire arranquen a tiempo) y se vuelven lentos de levantar y frágiles de mantener.&lt;/p&gt;</description></item><item><title>Arquitectura en capas para frontend React</title><link>https://patterns.exeal.com/patterns/arquitectura-en-capas-para-frontend-react/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/arquitectura-en-capas-para-frontend-react/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;En una SPA React sin fronteras internas, todo tiende a mezclarse dentro del componente que renderiza la pantalla: la llamada a la API, el estado de carga/error, la lógica de negocio (qué pedir, cómo combinar resultados, cuándo revalidar) y el JSX que lo pinta. El resultado es un componente que solo se puede testear montándolo entero — con mocks de &lt;code&gt;fetch&lt;/code&gt;, de router, de lo que haga falta — y donde no hay forma de reutilizar la lógica en otro sitio ni de darle una historia de Storybook sin resolver antes media aplicación.&lt;/p&gt;</description></item><item><title>Arquitectura hexagonal (puertos y adaptadores) en .NET</title><link>https://patterns.exeal.com/patterns/arquitectura-hexagonal-puertos-y-adaptadores/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/arquitectura-hexagonal-puertos-y-adaptadores/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Cuando la lógica de aplicación y la infraestructura (base de datos, storage, proveedores externos) conviven en el mismo proyecto, es fácil que un caso de uso acabe llamando directamente a un &lt;code&gt;DbContext&lt;/code&gt;, un cliente HTTP o &lt;code&gt;HttpContext&lt;/code&gt;. El código compila, funciona, pero deja de ser unit-testable: cualquier test de un caso de uso arrastra un contenedor de base de datos o un mock del framework web. Con el tiempo esto también acopla el dominio a decisiones de infraestructura que deberían poder cambiar solas — cambiar de ORM, servir el mismo core desde dos hosts distintos (uno con infraestructura real y otro en memoria para tests de frontend), o simplemente entender qué necesita realmente un caso de uso del mundo exterior.&lt;/p&gt;</description></item><item><title>CLI de seed de escenarios de prueba contra base de datos local</title><link>https://patterns.exeal.com/patterns/cli-de-seed-de-escenarios-contra-postgres-local/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/cli-de-seed-de-escenarios-contra-postgres-local/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Un sistema con varias máquinas de estado (un pedido, un cobro, una verificación de identidad&amp;hellip;) tiene decenas de combinaciones de estado posibles, y muchas de ellas dependen de integraciones externas (una pasarela de pago, un proveedor de scoring, un servicio de verificación) que tardan, cuestan o simplemente no se pueden disparar a demanda en local. Para llegar a probar a mano un caso concreto — por ejemplo, un pedido rechazado por scoring, o uno con la verificación de dirección fallida — habría que arrastrar un pedido real por todo el flujo: crearlo, esperar la respuesta del proveedor de turno, forzar el caso concreto que se quiere ver.&lt;/p&gt;</description></item><item><title>DSM Snapshot: matriz de dependencias entre módulos versionada</title><link>https://patterns.exeal.com/patterns/dsm-snapshot/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/dsm-snapshot/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;En cualquier arquitectura modular (features, bounded contexts, capas) el acoplamiento interno se degrada con el tiempo sin que nadie lo note. Un import &amp;ldquo;de conveniencia&amp;rdquo; cruza una frontera que el diagrama de arquitectura dice que no debería cruzarse, o convierte una dependencia unidireccional en un ciclo. Nada lo impide técnicamente — el compilador no sabe que &amp;ldquo;Feed no debería depender de Chat&amp;rdquo; — así que solo lo frena la memoria y la disciplina del equipo, que no escalan. El resultado se descubre meses después, en una auditoría o cuando alguien intenta extraer un módulo y se encuentra un grafo de dependencias mucho más enredado de lo que el diagrama sugería.&lt;/p&gt;</description></item><item><title>Fake OIDC: proveedor de autenticación de mentira</title><link>https://patterns.exeal.com/patterns/fake-oidc/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/fake-oidc/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Una API que autentica con OIDC no se puede levantar en local ni ejercitar en tests de aceptación sin resolver antes &amp;ldquo;¿contra qué me autentico?&amp;rdquo;. Apuntar a un proveedor OIDC real de verdad (Zitadel, Auth0, lo que sea) para desarrollo local o para CI trae credenciales que gestionar, usuarios de prueba que crear y mantener a mano en una consola externa, y dependencia de red contra un servicio que no controlas. La alternativa fácil — saltarse la autenticación en local con un middleware que la desactiva, o mockear el token a mano — hace que ni el pipeline de auth real ni el contrato HTTP real se ejerciten nunca fuera de producción, así que un bug de autenticación no aparece hasta que ya está desplegado.&lt;/p&gt;</description></item><item><title>Snapshot de contrato OpenAPI aceptado explícitamente</title><link>https://patterns.exeal.com/patterns/snapshot-contrato-openapi/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/snapshot-contrato-openapi/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Cuando el contrato HTTP de una API se genera automáticamente a partir del código (controladores, DTOs, atributos), nadie lo &amp;ldquo;escribe&amp;rdquo; a mano — y por eso nadie lo revisa a propósito tampoco. Un refactor interno que renombra un campo, cambia su tipo, o hace opcional algo que antes era obligatorio, cambia el contrato público como efecto secundario silencioso: compila, los tests unitarios pasan, y el PR se fusiona sin que nadie haya mirado el swagger. El consumidor de esa API (un frontend, otro servicio, un cliente externo) se entera cuando algo se rompe en producción, no en la revisión del cambio.&lt;/p&gt;</description></item><item><title>Tests de aceptación de backend sobre una imagen Docker ya construida</title><link>https://patterns.exeal.com/patterns/tests-aceptacion-sobre-imagen-docker/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/tests-aceptacion-sobre-imagen-docker/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Un backend .NET no se despliega como código fuente: se despliega como imagen Docker. Entre el código que pasa los tests unitarios y la imagen que corre en producción hay una capa entera que ningún test contra el código fuente toca — el &lt;code&gt;Dockerfile&lt;/code&gt;, las variables de entorno que el contenedor espera recibir, si el puerto publicado es el correcto, si las migraciones corren al arrancar, si el healthcheck responde. Un &lt;code&gt;WebApplicationFactory&lt;/code&gt; o un test de integración que arranca la app in-process compila contra las mismas clases que ya se probaron, así que no puede detectar ninguno de esos fallos — están todos fuera del código, en el empaquetado.&lt;/p&gt;</description></item><item><title>Tests de aceptación de frontend sobre una imagen Docker ya construida</title><link>https://patterns.exeal.com/patterns/tests-aceptacion-frontend-sobre-imagen-construida/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/tests-aceptacion-frontend-sobre-imagen-construida/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Un frontend construido con Vite y servido como estático (nginx) no se despliega como código fuente: se despliega como imagen Docker. Una suite de Playwright que arranca contra &lt;code&gt;vite dev&lt;/code&gt; o contra un build en el propio runner de CI no ejercita nada de lo que hay entre ese código y el artefacto real — el &lt;code&gt;Dockerfile&lt;/code&gt;, si nginx sirve las rutas de la SPA correctamente, si el entrypoint que inyecta la configuración en tiempo de arranque (ver el patrón de runtime env config) realmente deja la app apuntando a la API correcta. Todo eso puede pasar los tests unitarios y de componente y romperse solo en la imagen empaquetada.&lt;/p&gt;</description></item><item><title>Tests de persistencia del repositorio real</title><link>https://patterns.exeal.com/patterns/tests-de-persistencia-del-repositorio-real/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate><guid>https://patterns.exeal.com/patterns/tests-de-persistencia-del-repositorio-real/</guid><description>&lt;h2 id="problema"&gt;Problema&lt;/h2&gt;&#10;&lt;p&gt;Con el patrón Repositorio, la lógica de negocio se testea contra una implementación fake en memoria del repositorio: rápida, sin dependencias externas, perfecta para cubrir reglas de negocio con muchos casos. El problema es que esos tests solo prueban la lógica de negocio — nunca ejercitan la implementación real del repositorio, la que de verdad habla con la base de datos en producción.&lt;/p&gt;&#10;&lt;p&gt;Eso deja un hueco concreto: una query LINQ que EF Core no puede traducir a SQL y falla en tiempo de ejecución, un &lt;code&gt;GroupBy&lt;/code&gt;/&lt;code&gt;Join&lt;/code&gt;/&lt;code&gt;Distinct&lt;/code&gt; que en memoria cuenta bien porque ejecuta el mismo predicado C# pero en SQL agrupa distinto, una constraint única que en producción vive en el esquema de la base de datos pero que el fake in-memory no reproduce porque no impone ninguna unicidad, una condición de carrera que solo se resuelve con un &lt;code&gt;INSERT ... ON CONFLICT&lt;/code&gt; real. Nada de esto puede fallar en un test contra el fake, porque el fake y la implementación real solo comparten la interfaz — su comportamiento interno es completamente distinto. El fake existe justamente para no pagar el coste de hablar con una base de datos real en cada test de negocio, así que por construcción no puede detectar estos fallos.&lt;/p&gt;</description></item></channel></rss>