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.


