Testing
2. Usando el callback
3. Con
testing asíncrono en Jest con Promises y async await
- javascript
- Testing
- Asynchronous testing
- jest
- Promises
- async await
- Mocking
- Unit test
- integration test
🧠 Conceptos clave
- En Jest, las pruebas asíncronas validan comportamientos que dependen de operaciones no bloqueantes como llamadas HTTP, temporizadores o acceso a bases de datos.
- Es fundamental manejar correctamente la resolución o rechazo de promesas para evitar falsos positivos.
- Jest ofrece tres principales formas de manejar asincronía:
- Devolviendo una Promise desde el test.
- Usando la función
done()(callback tradicional). - Empleando funciones
async/awaitpara una sintaxis más clara y controlada.
⚙️ Estructura básica de un test asíncrono
1. Devolviendo una Promise
El test finaliza cuando la Promise se resuelve o rechaza.
test('devuelve datos del usuario', () => {
return fetchUser().then(user => {
expect(user.name).toBe('Eduardo')
})
})
`
2. Usando el callback done
El método más antiguo, útil en casos con múltiples callbacks.
test('usa done para esperar finalización', done => {
getData(data => {
expect(data).toBeDefined()
done()
})
})
3. Con async/await (recomendado)
Ofrece la sintaxis más clara y moderna.
test('resuelve correctamente con async/await', async () => {
const data = await fetchUser()
expect(data.id).toBe(1)
})
🚫 Manejo de errores y rechazos
Jest necesita saber cuándo una promesa falla correctamente.
Puedes testear rechazos de varias formas:
// con async/await
test('rechaza con error', async () => {
await expect(fetchUser(999)).rejects.toThrow('User not found')
})
// con Promises
test('rechaza usando then/catch', () => {
return fetchUser(999).catch(e => {
expect(e.message).toMatch(/not found/i)
})
})
🧩 Combinando async y mocks
Puedes usar jest.fn() o jest.mock() para simular funciones asíncronas.
const getUser = jest.fn(async id => ({ id, name: 'TestUser' }))
test('usa mock async', async () => {
const user = await getUser(5)
expect(user.name).toBe('TestUser')
expect(getUser).toHaveBeenCalledWith(5)
})
También se puede usar mockResolvedValue() o mockRejectedValue():
import axios from 'axios'
jest.mock('axios')
test('llamada HTTP mockeada', async () => {
axios.get.mockResolvedValue({ data: { name: 'Edu' } })
const res = await axios.get('/api/user')
expect(res.data.name).toBe('Edu')
})
🕒 Testing de temporizadores asíncronos
Jest permite simular tiempo para tests que dependen de setTimeout o setInterval.
jest.useFakeTimers()
test('simula timeout', () => {
const callback = jest.fn()
setTimeout(callback, 2000)
jest.advanceTimersByTime(2000)
expect(callback).toHaveBeenCalled()
})
Esto evita esperas reales y mantiene los tests deterministas.
🧱 Ejemplo práctico de test asíncrono real
// api.js
export const fetchUser = async (id) => {
const response = await fetch(`/users/${id}`)
if (!response.ok) throw new Error('User not found')
return response.json()
}
// api.test.js
global.fetch = jest.fn()
test('obtiene usuario correctamente', async () => {
fetch.mockResolvedValueOnce({
ok: true,
json: async () => ({ id: 1, name: 'Eduardo' })
})
const data = await fetchUser(1)
expect(data.name).toBe('Eduardo')
})
test('lanza error si no se encuentra el usuario', async () => {
fetch.mockResolvedValueOnce({ ok: false })
await expect(fetchUser(2)).rejects.toThrow('User not found')
})
🔄 Tests asíncronos en integration test
- En tests de integración, las operaciones asíncronas son comunes (p. ej. APIs, DBs).
- Usa
beforeAllyafterAllpara preparar y limpiar datos.
beforeAll(async () => await connectDB())
afterAll(async () => await disconnectDB())
test('inserta y lee un registro', async () => {
await saveUser({ id: 1, name: 'Ana' })
const user = await getUser(1)
expect(user.name).toBe('Ana')
})
💡 Buenas prácticas
- Evita el uso de
done()salvo en casos heredados. - No mezcles
async/awaitcondone, puede causar falsos positivos. - Usa
await expect(...).rejectspara errores, nuncatry/catchsi no es necesario. - Mantén tus mocks asíncronos simples y consistentes.
- En CICD, usa
--runInBandsi tienes problemas de sincronización con recursos compartidos.
📚 Recursos y documentación
- Jest - Testing Asynchronous Code
- Async/Await en JavaScript - MDN
- Mocking avanzado con funciones asíncronas.
- integration test en entornos con datos reales.
¿Quieres que la próxima nota sea **[Cobertura de código en Jest y análisis con SonarQube](/testing/cobertura-de-c-digo-en-jest-y-an-lisis-con-sonarqube/)**?
Puedo generarla siguiendo el mismo formato ampliado, centrado en cobertura, reportes y análisis de calidad.
¿Te gusta este contenido? Suscríbete vía RSS