Uso de async/await en Mocha: la prueba se bloquea o termina con un rec

Uso de async/await en Mocha: la prueba se bloquea o termina con un rechazo de promesa no controlado

Ejecutando una prueba muy simple en la que paso credenciales no válidas dentro del encabezado de autorización básica y espero que el servidor devuelva 401

const request = require('request-promise');
const expect = require('chai').expect;
const basicToken = require('basic-auth-token');

describe('PUT Endpoint', function () {
 it.only('should return unauthorized if basic token is incorrect', async function (done) {
                let options = {
                    url: `http://url_to_handle_request`,
                    resolveWithFullResponse: true,
                    headers: {
                        Authorization: `Basic ${basicToken('INVALID', 'CREDENTIALS')}`
                    }
                };

                try {
                    await request.put(options); // this should throw exception
                } catch (err) {
                    expect(err.statusCode).to.be.equal(401); // this is called
                }
                done();
            });
});

El problema con este código es que la cláusula expect se resuelve en falso (porque el servidor respondió, por ejemplo, con 403) y la prueba termina con un error:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError: expected 403 to equal 401

Si omito la devolución de llamada done, la prueba simplemente se cuelga (el nombre está en rojo) y aparentemente está "esperando" a que algo termine ingrese la descripción de la imagen aquí

Sé que funcionará si lo reescribo para usar el enfoque de promesas estándar. Tengo curiosidad por saber cómo hacerlo a través de async/await.

Gracias

Mostrar la mejor respuesta

Elimine done del parámetro (y también del cuerpo de la función), luego Mocha esperará que devuelva Promise.

Las funciones asíncronas devuelven promesas de forma predeterminada.

Si no arroja un error, devuelve una promesa resuelta.

Gracias. Anteriormente lo tenía implementado de esta manera pero no pude ver ninguna diferencia. Así que me sumergí en el código y me di cuenta de que era la función after la que causaba esto. Así que hice correcciones tanto en el asíncrono como en el after y comenzó a funcionar

Si no se maneja un rechazo de promesa ni se arroja un error, se denomina estado 'falso'. Lea esta publicación: ravichandranjv.blogspot.in/2018 /03/… - para una explicación completa de las promesas. Una respuesta sin código de soporte no es realmente una respuesta. Por favor, publique el código de apoyo para su respuesta,

@ user2347763: lo siento, eso no es correcto. Lanzar un error en la función asíncrona conduce a devolver la Promesa rechazada, lo que conduce a una prueba descartada correctamente con el mensaje de error adecuado. Cuando no coloca la variable done dentro de la prueba, esperará devolver la promesa (que la función asíncrona siempre hace) en lugar de devolver la llamada.

@libik: consulte la publicación del blog para obtener una explicación más elaborada con el código. Si está diciendo que se debe llamar a done porque la función asíncrona proporcionó la devolución de llamada, entonces ese es un problema completamente diferente. Su declaración de que "si no arroja un error, devuelve una promesa resuelta" no es del todo correcta porque una promesa tiene un estado falso cuando se devuelve una promesa vacía y su declaración es en realidad el estado falso que dice que es una promesa resuelta.

@ user2347763: lo siento, esa publicación de blog no está relacionada con la pregunta OP y por sí sola no dice mucho y su calidad es baja. No hay nada como el estado falsey para las pruebas de mocha, solo puede haber resuelto o rechazado la promesa (si omite la devolución de llamada). Devolver una promesa vacía resuelta (que tiene un valor nulo o indefinido) es una forma estándar para las funciones nulas.

@libik sí, no lo es. Acabo de publicar el enlace para que pueda consultar la captura de pantalla de los mensajes que muestra nodejs. No puedo publicar la captura de pantalla de un estado falso, así que editaré tu publicación si te parece bien. Si no, simplemente puede rechazar la edición.

@ user2347763: no actualice otras respuestas con sus propias opiniones. La edición solo debe usarse para algunos cambios de formato o correcciones claras (es decir, enlace roto...).

Sí, he mencionado claramente el motivo de la edición en mi comentario. De ninguna manera es mi opinión. Dado que no admitirá que un estado falso es en realidad un estado de promesa a pesar de la captura de pantalla que puse como referencia, actualizaré mi respuesta con la captura de pantalla para su referencia. Me gustaría que respondiera cómo afirmó que no hay nada como el estado falso para las pruebas de mocha cuando el mensaje de nodejs establece claramente el estado de la promesa en el resultado de la prueba.

Cambiar este bloque de código

try {
                    await request.put(options); // this should throw exception
                } catch (err) {
                    expect(err.statusCode).to.be.equal(401); // this is called
                }
                done();

a

                await request.put(options)
                    .then(()=>{ })
                    .catch(function (err)){ 
                      expect(err.statusCode).to.be.equal(401);
                     }

Esto realmente no funciona correctamente, si se arroja un error, el hecho nunca se llama

@libik: ¿sabes qué son las promesas y cuándo se llama? Para un rechazo de promesa no resuelto, la advertencia de excepción dice claramente que terminará el proceso, entonces, ¿qué quiere decir con que nunca se llama a hecho si se produce un error? El bloque .catch ayuda a manejar el rechazo de la promesa no resuelta.

Tienes .catch allí, significa que no es una promesa sin resolver. Si request.put arroja un error, salta a catch (sin usar entonces ->), usa expect y si pasa, esperará 2 segundos y luego lo rechazará con tiempo de espera (o más segundos, si configura global tiempo de espera a un valor diferente)

Si pasa la prueba, es decir, espera 403 y no 401, entonces el programa (mocha) sale correctamente.

En realidad no, lo siento. Si hay un error, no se llama a .then(() => done()). Digamos que expect(401) es correcto para el err.statusCode esperado, entonces esto pasa y estará esperando done(), que nunca se llama y termina con un error: tiempo de espera

Bueno, sí, lo que dices es cierto, pero dado el código, incluso done() en el bloque .then no es aplicable porque es una resolución excesiva. Debe ser una devolución de llamada o una promesa, no pueden ser ambas.

Después de esta actualización y ningún otro cambio, fallará con un error de promesa rechazada o un error de tiempo de espera. Nunca pasa como hecho nunca se llama.

Hay un mensaje de SO para evitar discusiones extensas en los comentarios, por lo que concluirá la refutación de su declaración de que llamar hecho en una resolución de promesa es una especificación excesiva.

Falsey está relacionado solo para promesas rechazadas y solo si hace algo como "arrojar nulo", lo que nunca podría suceder en el ejemplo de programación orientada a objetos. Nunca me he encontrado con eso en mi vida.

@libik: estoy seguro de que sabe qué son las promesas, pero solo porque no haya encontrado una posibilidad, no significa que no exista. Falsey es un estado de rechazo de una promesa que ni arroja un error ni provoca ningún fallo, es un fallo simple, silencioso. Incluso en la publicación del OP, resolveWithFullResponse puede fallar fácilmente en silencio con medio búfer o sin respuesta, lo que provoca una falla silenciosa de la solicitud y no es necesario que sea un "lanzamiento nulo".

No hay nada como "Rechazo de promesa que ni arroja error ni provoca fallo alguno". La promesa es rechazada o resuelta -> nada intermedio. Si la promesa rechazada no tiene el error adecuado dentro, puede generar algunos problemas de salida, ya que espera un objeto con message y stack dentro.

¿Puede decirme a quién está tratando de influir con sus comentarios? Porque ya he compartido con usted la captura de pantalla de nodejs necesaria para un estado falso de una promesa y su persistencia simplemente influye en las respuestas negativas a mi comentario. Le pediría que acepte que existe una posibilidad falsa de una promesa y que su respuesta al OP es en realidad una falsa más inválida porque su respuesta sugiere el uso de una promesa falsa y una devolución de llamada, lo cual, node.js respondería con una especificación excesiva error, solo puede usar una devolución de llamada o una promesa.