javascript - supertest falla con ECONNRESET
Estoy trabajando en un proyecto de Node.js y tratando de escribir casos de prueba para la aplicación. Los endpoints funcionan perfectamente cuando los ejecuto en Postman. Pero cuando ejecuto los casos de prueba, algunos de ellos (generalmente el primero en el orden) falla con el error
- Error: read ECONNRESET
He intentado depurarlo, busqué una posible solución, pero no puedo arreglarlo. Estoy trabajando con jasmine/supertest por primera vez. Quizás me esté perdiendo algo que no puedo anticipar, pero no he podido descubrir cuál es el problema. ¿Alguien puede ayudarme con esto? Muchas gracias de antemano.
Aquí está mi código de prueba.
it('Gets Users List', async() => {
const response = await request.get('/users')
expect(response.status).toBe(200);
})
y mi función de controlador
export const index = async (req:Request, res: Response) => {
try {
const users : DataObject = await model.index()
res.status(users.status);
res.json(users.data);
} catch (error) {
res.status(NOT_FOUND);
res.json(error);
}
}
El comportamiento peculiar que observé es que cuando añado otro método antes de este, entonces este método funciona bien y el primero devuelve el mismo error. Supongo que la primera llamada es rechazada debido al hecho de que la conexión aún no se había establecido. Sin embargo, no estoy seguro.
¿Alguien familiarizado con este problema?
Gracias de antemano.
Respuesta #1
Para que otros puedan beneficiarse, en los comentarios @rwheadon mencionó que para ellos era una condición de carrera.
Puedo confirmar que ese también fue nuestro caso.
Este es el código final funcional para nosotros:
it('should fail without a valid token', (done) => {
// After multiple hours of trying to get it to work, we figured out that
// _in this specific test_, the file being consumed on the same tick as
// the request being sent causes an issue where the server has an
// ECONNRESET error. This is not an issue normally, or in any other
// test, only for this test.
const file = fs.createReadStream(path.join(process.cwd(), uploadExcelFile));
setTimeout(() => {
localSuperTest
.post(`/upload-redeem-codes`)
.attach('file', file)
.expect(401)
.end((err: any, res: any) => {
if (err) {
return done(err);
}
assert.equal(res.body.message, 'not authorized');
done();
});
});
});
De alguna manera, hay una condición de carrera en las pruebas al usar .attach() con supertest.
El punto principal, creemos, es que leer el archivo y luego consumir el archivo (con el .attach('file', file)) tienen que estar en dos ciclos diferentes en el bucle de devolución de llamada.
Espero que eso le ahorre a un pobre alma varias horas de investigación.
Respuesta #2
Para mí, el setTimeout no funcionó. En mi caso, se resolvió creando un nuevo agente http y agregándolo a la solicitud.
it('Should return status 400 when file type is not .docx', async () => {
try {
// Explicit socket timeout
const agent = new http.Agent({
keepAlive: true,
maxSockets: Infinity,
timeout: 10000
});
const response = await request(app)
.post('/api/preprocess')
.type('form')
.attach('file', jsonFilePath, 'data.json')
.field('data', JSON.stringify(data))
.field('startDelimiter', '<')
.field('endDelimiter', '>')
.agent(agent)
.expect(400);
expect(response.body.message).toBe('Wrong file type');
expect(response.body.errorCode).toBe(102);
} catch (error) {
Logger.warn('Comprehensive error details:', {
errorName: error.name,
errorMessage: error.message,
errorStack: error.stack,
errorProperties: error.properties
});
throw error;
}
});
Esta es la solución de cómo funcionó para mí.
