Probando un gancho personalizado UseInterval con jest.
Mi gancho es:
function useInterval() {
const ref = useRef(null);
function set(callback, delay) {
ref.current = setInterval(callback, delay)
}
function clear() {
if (ref.current) {
clearInterval(ref.current)
ref.current = null
}
}
return { set, clear }
}
Mi prueba es:
it("set: Esto debería ser llamado 10 veces", () => {
var callback = jest.fn();
jest.useFakeTimers()
const { result } = renderHook(() => hooks.useInterval())
act(() => {
result.current.set(() => { callback }, 100);
jest.advanceTimersByTime(1000);
})
expect(callback).toHaveBeenCalledTimes(10);
jest.useRealTimers()
})
renderHook()
y act()
provienen de "@testing-library/react-hooks": "^7.0.2"
El resultado que sigo obteniendo es 0
en mi llamada expect()
. No puedo encontrar la razón.
Si solo uso setInterval()
, expect()
obtiene el valor correcto.
it("setInterval", () => {
var callback = jest.fn();
jest.useFakeTimers()
setInterval(callback, 100)
jest.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalledTimes(10);
jest.useRealTimers()
})
He intentado reordenar las líneas de todas las formas lógicas posibles que se me ocurren.
He notado que obtengo el mismo resultado con o sin act()
, extrañamente.
Agregar timers: "fake"
o cualquiera de sus variaciones (modern/legacy) a jest.config.ts
no parece tener ningún efecto.
Obviamente, testing-library/react-hooks
de alguna manera está ocultando setInterval()
de jest.useFakeTimers()
, pero no entiendo cómo y, por lo tanto, no puedo obtener el resultado que espero.
Parte de mí piensa que mi gancho no está siendo afectado por jest.useFakeTimers()
porque los temporizadores falsos no se están reemplazando globalmente, pero no sé cómo hacer esto.
Además, estoy usando Typescript. Aunque no creo que eso haga una diferencia.
davy.ai
Solución de problemas de un caso de prueba fallido para un gancho React personalizado
El problema
La llamada
expect()
en el caso de prueba proporcionado devuelve0
, lo que indica que la funcióncallback
pasada al métodoset()
del gancho personalizadouseInterval()
no se ha llamado. El mismo caso de prueba consetInterval()
en lugar del gancho personalizado funciona como se esperaba.Posibles causas
jest.useFakeTimers()
podría no estar simulando correctamentesetInterval()
yclearInterval()
en el contexto del gancho personalizado.act()
podría no ser necesario o podría no usarse correctamente en este caso de prueba.Posibles soluciones
jest.useFakeTimers()
, intente sustituir la funciónconsole.log()
porjest.advanceTimersByTime()
en el caso de prueba y verifique si la salida muestra el número esperado de registros.Si la salida en la consola es la esperada pero la función
callback
aún no se está llamando, el problema podría estar relacionado con la interacción entre la biblioteca de pruebas y el gancho personalizado, como se explica a continuación.Para solucionar el problema de
act()
, intente eliminarlo del caso de prueba y verifique si la aserciónexpect()
se cumple.Si la aserción
expect()
se cumple sinact()
, puede que no sea necesario en este caso de prueba. Si falla, intente envolver todo el caso de prueba dentro deact()
.renderHook()
yact()
.renderHook()
y se extraiga correctamente el resultado.set()
yclear()
del gancho personalizado se llamen con los argumentos correctos y se comporten como se esperaba.Si ninguna de las soluciones anteriores funciona, intente actualizar la versión de las bibliotecas de pruebas utilizadas (
@testing-library/react-hooks
y/ojest
) a la última versión estable. Si el problema persiste, consulte la documentación y/o abra un problema en el repositorio respectivo.