Jest: async / await toThrow no funciona

Creado en 15 sept. 2016  ·  21Comentarios  ·  Fuente: facebook/jest

próxima prueba

async function check() {
  throw new Error('Test');
}

expect(async () => 
  await check()
).toThrow();

fallará y no detectará el error correctamente (estoy usando la última versión de broma)

Comentario más útil

En lugar de

expect(async () => await check()).toThrow()
// Jest error: "Expected the function to throw an error. But it didn't throw anything."

esto funciona:

expect(check()).rejects.toEqual(new Error('Test'))

Sí, la sintaxis es incómoda ...

Todos 21 comentarios

Sí, esto no es compatible actualmente. Ver https://github.com/facebook/jest/issues/1377

En lugar de

expect(async () => await check()).toThrow()
// Jest error: "Expected the function to throw an error. But it didn't throw anything."

esto funciona:

expect(check()).rejects.toEqual(new Error('Test'))

Sí, la sintaxis es incómoda ...

También puedes escribir:

let error;
try {
  await check();
} catch (e) {
  error = e;
}
expect(error).toEqual(new Error('Test'));

Lo siguiente también funcionó para mí:

async function check() {
  throw new Error('Test');
}

expect(check()).rejects.toEqual(new Error('Test'))

Ver: https://facebook.github.io/jest/docs/en/tutorial-async.html#rejects

Añadiendo a la lista de soluciones.
Si te gusto, quieres detectar un tipo de error específico y no me importa el mensaje:

async function check() {
  throw new SomeSpecificError('Whatever');
}

await check()
  .then(() => {
    throw new Error('Should go to .catch, not enter .then');
  })
  .catch((err) => {
    expect(err).toBeInstanceOf(SomeSpecificError);
  });
await expect(check).rejects.toThrow(SomeSpecificError);

Debería funcionar también

await expect(check).rejects.toThrow(/DUPLICATES_DETECTED/);

es lo que hago.

async function check() {
  throw new Error("Test");
}
await expect(check).rejects.toThrow(Error);
expect(received).rejects.toThrow()

received value must be a Promise.
Received:
 function: [Function check]

Debes invocarlo para darle la promesa real.

async function check() {
  throw new Error("Test");
}
await expect(check()).rejects.toThrow(Error);

Debería funcionar también

it(`some test`, async () => {
  async function check() {
    try {
      return Promise.reject(await asyncMethod());
    } catch (error) {
      throw new Error("test");
    }
  }
  await expect(check()).rejects.toThrow(Error);
});

puede trabajar

versión

  • broma: 23.4.2
  • ts-broma: 23.1.2

Sé que necesita una promesa, pero el caso que estás ofreciendo no lo es :)

Hola ! Puede que esté haciendo algo mal, pero todavía tengo un problema con los errores personalizados en las llamadas asíncronas. Considera lo siguiente:

class CustomErrorType {}
// ...
test('check throws custom error', async () => {            
    async function check() {
        throw new CustomErrorType();
    }
    await expect(check()).rejects.toThrow(CustomErrorType);
});

entonces la prueba falla con el siguiente resultado:

Se esperaba que la función arrojara un error de tipo:
"CustomErrorType"
Pero no arrojó nada.

Entonces la prueba falla, mientras que funciona perfectamente cuando la clase lanzada es Error . Cuando intento extender Error con
`` `javascript
class CustomErrorType extiende Error {}
`` ``

entonces el error es

Se esperaba que la función arrojara un error de tipo:
"CustomErrorType"
En cambio, arrojó:
Error

¿Alguna pista sobre algo que está mal en esa muestra? Estoy usando broma 23.4.2.

@Marchelune Cuando escribe class CustomErrorType extends Error {} no ha definido una nueva clase. Si le da a CustomErrorType un cuerpo, incluso solo un constructor que no hace nada más que llamar a super (), funcionará.

En caso de que alguien arroje algo diferente de la clase Error de instancia y tenga dificultades para usar los consejos de ese hilo (como lo hice yo).
toThrow() comprobará qué valor arrojado es la instancia de la clase Error, y si no es así, no se detectará el lanzamiento. Esto no era obvio por los documentos y el sentido común.
Esto fallará, aunque claramente arroja:

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toThrow()`

pero esto funcionará (no estoy seguro si hay una mejor manera):

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`

@Karabur error tipográfico toBeThruthy debe ser toBeTruthy

Aquí hay una prueba explícita que asegura que definitivamente se romperá si NO arroja y coincide con un error específico.

yourCoolAsyncMethod('yeah it is')
    .then(ok => { // Presumes not a Promise<void>
        expect(ok).toBeUndefined();
        done();
    })
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

Hola @SimenB.
Si tengo esto y está funcionando.

async function check() {
    // do something
}
await expect(check()).rejects.toThrow(InternalServerErrorException);

InternalServerErrorException se lanza con un objeto ....

¿Cómo puedo afirmar también las propiedades en el error arrojado? Por ejemplo:

  • exception.message = 'ERROR'
  • exception.status = '500'

Aquí hay una prueba explícita que asegura que definitivamente se romperá si NO arroja y coincide con un error específico.

yourCoolAsyncMethod('yeah it is')
    .then(ok => {
        expect(ok).toBeUndefined();
        done();
    })
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

El problema de esto es que su prueba pasará si el código nunca tiene errores.

Por lo tanto, esta prueba no ofrecería mucho valor, ya que los resultados esperados varían en función de si el código que está probando tiene un error o no.

Las pruebas deben tener un flujo negativo o positivo y solo debemos probar lo que se necesita para probar. Este tipo de aleatoriedad no es el mejor.

Hola @ David-Tennant 🖐

Gracias por señalar eso. Estaba trabajando en un método Promise<notVoid> en ese momento. Me di cuenta de que no compartía una solución común que también sea válida para Promise<void> . Actualicé mi respuesta con un comentario que dice que hice suposiciones. Estoy de acuerdo contigo sobre el flujo.

Gracias 💨

Hola @futuredayv 👋

Hola @ David-Tennant 🖐

Gracias por señalar eso. Estaba trabajando en un método Promise<notVoid> en ese momento. Me di cuenta de que no compartía una solución común que también sea válida para Promise<void> . Actualicé mi respuesta con un comentario que dice que hice suposiciones. Estoy de acuerdo contigo sobre el flujo.

Gracias 💨

El problema es que su prueba aún se aprobará si la prueba vuelve nula. ¿Cuál debería ser un error, verdad?
Llamar a done() significa "Mi prueba pasó de la manera esperada y estoy listo para pasar a la siguiente prueba".

yourCoolAsyncMethod('yeah it is')
     // -- Lets say your method does not throw, and returns void instead
    .then(ok => { // Presumes not a Promise<void>
        expect(ok).toBeUndefined(); // -- At this point if it was void, this would pass
        done(); // -- Then your test would end and the catch would not be reached
        // -- Now you have unknown behavior passing a test where it's suppose to catch a fail
    })
    .catch(bad => {
        // -- This block does not run because done() is called above
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

No estoy seguro de cuál sería la solución para su caso de uso. Pero comenzaría por no llamar a done() en then o tal vez arrojar un error en el "entonces" para asegurarme de que la prueba falla,

yourCoolAsyncMethod('yeah it is')
    .then(ok => throw new Error("This block of code should not be reached")
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

En caso de que alguien arroje algo diferente de la clase Error de instancia y tenga dificultades para usar los consejos de ese hilo (como lo hice yo).
toThrow() comprobará qué valor arrojado es la instancia de la clase Error, y si no es así, no se detectará el lanzamiento. Esto no era obvio por los documentos y el sentido común.
Esto fallará, aunque claramente arroja:

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toThrow()`

pero esto funcionará (no estoy seguro si hay una mejor manera):

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`

Una forma un poco mejor es usar toBeDefined() lugar de toBeTruthy() :
async function f() {throw 'aa'} const res = await expect(f()).rejects.toBeTruthy()`

¿Fue útil esta página
0 / 5 - 0 calificaciones