El patrón de diseño Mother lo vi inicialmente en este post de Martin FowlerSe abre en una nueva pestaña. Lo uso para gestionar datos de prueba (fixtures) e incluso para mockear pantallas de forma coherente, predecible y reutilizable. Aquí tienes una guía práctica y simplificada para que lo apliques paso a paso.
#¿Qué problema resuelve?
- Evita duplicar estructuras de datos complejas.
- Hace explícitas variantes habituales (por ejemplo "usuario válido", "usuario con email inválido", etc).
- Permite sobreescribir (overrides) valores para adaptar solo lo necesario en cada test.
#¿Cómo aplicar el patrón mother?
Supongamos que tenemos un usuario:
interface User { id: number email: string }
Necesitamos tener en código una serie de datos de prueba. Para ello creamos un fichero user.mother.ts
export class UserMother { static base(): User { return { id: 1, email: 'user@example.com', } } }
Suelo usar para nombres de ficheros kebab-case y añado como sufijo la tipología.
En mis proyectos verás nombres como get-user.qry.ts o dashboard.page.tsx
Uso métodos estáticos para evitar tener que crear instancias. Para usar en un test sería así: UserMother.base().
describe('user validator', () => { it('should validate an user', () => { const user = UserMother.base() const isValid = userValidator.validate(user) expect(isValid).toBe(true) }) })
De esta forma no tendremos que repetir una y otra vez los mismos datos de prueba.
#Nombres con intención
Cuando creamos los mothers, me parece interesante darles nombres. Además, creo una historia acerca de la persona que quiero representar. Os presento a John y Jane. John es alguien que no es muy versado en la informática, es algo además despistado y, por tanto, suele tener errores en los datos que introduce.
Por otro lado, tenemos a Jane, experta en informática. Sus datos siempre están bien formados.
Con estas premisas vamos a mejorar el nombre .base e introducir estos usuarios.
export class UserMother { // Jane: persona experta, datos bien formados static jane(): User { return { id: 101, email: 'jane.doe@company.com', } } // John: persona principiante, datos mal formados static john(): User { return { id: 102, email: 'john..doe@@example', // email inválido } } }
#Overrides controlados con Partial<T>
¿Qué ocurre si necesita cambiar una propiedad del objeto para un test en concreto? Para eso tenemos los overrides:
export class UserMother { static base(override?: Partial<User>): User { const base: User = { id: 1, email: 'user@example.com', } return { ...base, ...override } } static jane(override?: Partial<User>): User { return this.base({ id: 101, email: 'jane.doe@company.com', ...override, }) } }
Todas las factorías aceptan override?: Partial<User>. Esto permite ajustar los campos sin perder la forma del objeto.
const user = UserMother.jane({ id: 999 })
Esta técnica minimiza ruido, mantiene consistencia y reduce el mantenimiento de tests.
#Consejos prácticos
- Mantén las variantes más usadas y elimina las que no aportan casos reales.
- Prefiere
overrideen lugar de crear una variante por cada combinación posible. - Extrae conversiones/serializaciones a funciones claras y testeables por separado.
- Usa valores que parezcan reales (fechas coherentes, duraciones consistentes) para detectar errores con mayor facilidad.
#Conclusión
El patrón mother permite crear conjuntos de datos para que los tests sean más mantenibles. Añadiendo nombres con intención y permitiendo hacer uso de overrides proveerás de mucho valor a la hora de hacer los tests.


