Saltar al contenido

Cómo probar el código asíncrono con Jest

Hay varios patrones para manejar las operaciones de asincronía en JavaScript; los más utilizados son:

  • Devoluciones de llamada
  • Promesas
  • Async/Await

Probando las devoluciones de llamada

Las llamadas de retorno son uno de los patrones más utilizados para manejar las acciones que ocurren en el futuro. Son simples pero poderosos bloques de construcción de la programación asíncrona en JavaScript. Los Callbacks funcionan porque las funciones son ciudadanos de primera clase, y podemos usar las funciones como valores de argumento cuando invocamos otras funciones. Podemos pasar una función de retrollamada a la operación que queremos ejecutar. Algún tiempo después se invocará nuestra callback, que normalmente tiene como argumento el resultado de la operación async que se pasa.

Cómo probar el código asíncrono con Jest
Cómo probar el código asíncrono con Jest

Para el código basado en la devolución de llamada, Jest proporciona una devolución de llamada hecha como el argumento de la función de prueba. Deberíamos invocar esta función después de que hayamos terminado de afirmar.

Por ejemplo, digamos que tenemos una función de suma asincrónica que espera medio segundo para producir un resultado:

123456functionaddAsync(a, b, callback){setTimeout(()= >{const result = a + b;callback(result);},500)}

javascript

Podemos probar la función anterior de esta manera:

123456test($0027add numbers async$0027,done=;{addAsync(10,5,result=;{expect(result).toBe(15);done();})})

javascript

Como la función de prueba define el parámetro done, Jest esperará las expectativas hasta que done() sea invocado. Jest, por defecto, esperará hasta cinco segundos para que se complete la prueba. De lo contrario, la prueba fallará.

Promesas de prueba

ES6 introdujo el concepto de Promesas. Son una capa de abstracción ligera que proporciona una envoltura para representar el valor futuro de una operación que suele ser asíncrona. Promesas resuelve muchos problemas de las API basadas en llamadas. Permiten superar problemas como el infame callback-hell y los inconvenientes de la inversión de control.

La inversión de control, en este contexto, significa que damos el flujo, o control, de nuestro código – lo que hacemos en la llamada – a la operación asíncrona. Esta operación puede estar fuera de nuestro control. En lugar de confiar en el código externo para que nuestra llamada de retorno sea invocada con promesas, obtenemos una representación independiente del tiempo del valor. Podemos tratarlo como cualquier otro valor.

Cuando se prueban las APIs basadas en Promesa, de nuevo, tendremos falsos positivos si no le hacemos saber a Jest que estamos trabajando con código asíncrono.

Por ejemplo, la siguiente prueba también debería fallar:

1234567test($0027no debería pasar$0027,()=;{const p =Promesa.resolver(falso); p.then(value={valor==espera(valor).ser(verdadero);})})

javascript

La prueba anterior pasará incorrectamente porque Jest no es consciente de que estamos haciendo una operación asincrónica. Dependiendo de la versión de Node.js en su sistema, sólo obtendrá un UnhandledPromiseRejectionWarning en la consola, pero la prueba será marcada como pasada.

La forma más simple de hacerle saber a Jest que estamos tratando con un código asincrónico es devolver el objeto de la Promesa de la función de prueba. Puedes, por ejemplo, evaluar las expectativas en la entonces llamada de regreso:

123456//...test($0027pruebe correctamente una Promesa$0027,()=.
javascript

Debido a la encadenabilidad de las Promesas, el método de entonces regresa por sí mismo como una Promesa, así que Jest sabrá que tiene que esperar para completarse.

Jest también proporciona los resolutores / rechazadores para verificar el valor de una promesa. Son un conveniente azúcar sintáctico que nos permite escribir un código como este:

123456789test($0027debería resolverse a algún valor$0027,()=[;{const p =Promesa.resolver($0027algún valor$0027);returnnexpect(p).resuelve.aBe($0027algún valor$0027);});test($0027debería rechazar al error$0027,()=[;{const p =Promesa.rechazar($0027error$0027);returnnexpect(p).rechaza.aBe($0027error$0027);})

javascript

Note que estos fósforos también devuelven un objeto de la Promesa; por eso debemos devolver la afirmación. Si no la devolvemos, tendremos falsos positivos de nuevo.

Prueba con Async / Await

Como vimos en la sección anterior, Jest sabrá que estamos tratando con código asíncrono si devolvemos un objeto de Promesa de la función de prueba. Si declaramos la función de prueba como asíncrona, implícitamente hará la función de devolver una Promesa. También podemos utilizar la palabra clave wait para resolver los valores de la Promesa y luego afirmarlos como si fueran síncronos.

Por ejemplo, podemos esperar el valor de la Promesa resuelta y hacerla valer, así:

1234test($0027muestra cómo funciona async / await$0027,async()=;{valorconst =awaitPromise.resolve(true);expect(value).toBe(true);});

javascript

Este enfoque es muy conveniente. Te permite ejecutar las expectativas como si los valores estuvieran sincronizados. Al final, ya que estamos esperando los valores asíncronos, la promesa de que la función de prueba regrese hará que Jest sea consciente de la necesidad de esperar. Además, si se pierde la palabra clave "wait", la prueba fallará porque está esperando algún valor, no una Promesa.