Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

supertest failing with ECONNRESET

I'm working on a Node.js project and trying to write test cases for the app. The endpoints are working perfectly fine when I run them in Postman. But when I run the test cases, some of them, (Usually the first one in the order) fails with the error

 - Error: read ECONNRESET

I have tried debugging it, searched for a potential solution, but I'm unable to fix it. I'm working with jasmine/supertest for the first time. Maybe I'm missing something I'm unable to anticipate but I haven't been able to find out the issue. Can anybody help me out with this? Thanks a bunch in advance.

Here is my test code.

 it('Gets Users List', async() => {
     const response = await request.get('/users')
    

    expect(response.status).toBe(200);
    
})

and my Controller function

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);
  }
}

The peculiar behavior that I observed is when I add another method before this one, then this method works fine and the first one returns the same error. I assume the first call is rejected due to the fact that connection was not established yet? I'm not sure though.

Anybody familiar with this issue?

Thanks in advance.

like image 343
Tauseef_Ahmed Avatar asked Nov 19 '25 20:11

Tauseef_Ahmed


2 Answers

So others can benefit, in the comments @rwheadon mentioned it was a race condition for them.

Can confirm that was the case for us as well.

This is the final working code for us:

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();
      });
    });
  });

Somehow, there is a race condition in tests when using .attach() with supertest.

The main point, we believe, is that reading the file, and then consuming the file (with the .attach('file', file), have to be on two different ticks in the callback loop.

I hope that saves a poor soul several hours of investigation.

like image 153
greduan Avatar answered Nov 21 '25 10:11

greduan


For me the setTimeout didn't work. In my case it got solved by creating a new http agent and adding it to the request.

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;
        }
    });

This is the solution how it worked for me.

like image 42
Antheriox Avatar answered Nov 21 '25 09:11

Antheriox



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!