ladjs / supertest

🕷 Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
MIT License
13.8k stars 757 forks source link

Uncaught Error: ECONNREFUSED: Connection refused #484

Open apoguy opened 6 years ago

apoguy commented 6 years ago

So I'm writing some tests using Mocha, chai and supertest.

I'm facing a really weird behavior here on a test that should work just fine. Here's the test code:

var app = require('../app/app');
var agent = request.agent(app);

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

//Run request tests
describe('Request Tests - Setting Enviroment', () => {

    before((done) => {
        //set TEST env
        process.env.TEST = true;
        //load app
        app.start().then(() => {
            done();
        });
    });

    describe('basic page request', () => {

        it('should respond with 200 respond code', () => {

            request(app).get('/login')
            .expect(200)
            .expect('Content-Type', 'text/html; charset=utf-8')
            .end((err, res) => {
                if (err) throw err;
            });

        });

    });

    //Server ready
    describe('Fuzz Test', () => {

        describe('fuzzing login page with 1000 username/password permutations', () => {

            fuzzer.seed(0);

            it('should respond with 403 / invalid csrf token', () => {

                for(var i=0; i <= 1000; i++){

                    request(app).post('/login')
                    .send({
                        username: fuzzer.mutate.string('fuzzfromhere'),
                        password: fuzzer.mutate.string('fuzzfromhere')
                    })
                    .expect((code) => {
                        if (code != 403 && code != 429) throw code;
                    })
                    .end((err, res) => {
                        if (err) throw err;
                    });

                }

            });

        });

        describe('fuzzing tokenizer page with 1000 random values', () => {

            it('should respond with response from External API or invalid value', () => {
                // touch env to skip login and rate limiter
                process.env.TEST = 'skipLogin,skipRateLimiter';
                //get csrf to validate queries
                request(app).get('/tokenize')
                .expect((response) => {
                    console.log(`expect resp: ${response}`);
                })
                .end((err, res) => {
                    if (err) throw err;
                    console.error(`expect error: ${err}`);
                });
            });

        });

    });

    //Tests completed, end server
    after((done) => {
        app.end().then(() => {
            delete process.env.TEST;
            done();
        }).catch((err) => {
            throw err;
        });

    });

});

For some weird reason, I am getting the following error:

    Request Tests - Setting Enviroment
    Fuzz Test
    fuzzing tokenizer page with 1000 random cards
    should respond with response from Key Manager or invalid number:
    Uncaught Error: ECONNREFUSED: Connection refused
    at Test.assert (node_modules\supertest\lib\test.js:165:15)
    at assert (node_modules\supertest\lib\test.js:131:12)
    at C:\Users...\src\node_modules\supertest\lib\test.js:128:5
    at Test.Request.callback (node_modules\superagent\lib\node\index.js:718:3)
    at ClientRequest.req.once.err (node_modules\superagent\lib\node\index.js:646:10)
    at TLSSocket.socketErrorListener (_http_client.js:387:9)
    at emitErrorNT (internal/streams/destroy.js:64:8)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)

Any idea what's causing this?

McPatate commented 6 years ago

Hi there,

Didn't you forget a done in your last 'it' ? Your output differs from what's written in your code also, make sure to double check.

Good luck !

JoshuaRabiu commented 6 years ago

Try starting app.js with npm start || yarn start instead of a before hook. If that doesn't work, you may want to try passing in the url of app to request.agent instead of using require. (Instead of : var agent = request.agent(app);, try: var agent = request.agent('127.0 0.1:YourPortHere');

apoguy commented 6 years ago

Only solution was to use:

it('should respond with invalid token', async function() {
  this.timeout(15000);

     for(var i=0; i<=hitsPerFuzz; i++){

          var url = `/miniDetokenize?token=${fuzzer.mutate.string('vX2Fet_z5sqy@Ss9')}`;

           await agent
          .get(url)
          .then(resp => {
              const $ = cheerio.load(resp.res.text);
              expect($('h2').html()).to.be.equal('Invalid token format.');
          })
         .catch(err => {
             throw err;
        });

    }

});

Making synchronous requests to avoid using up all the sockets. I don't know if supertest supports concurrency, but this is how I managed to do it.

Iworb commented 6 years ago

I have a similar problem with multiple users supertest:

process.env.NODE_ENV = 'test'
require('module-alias/register')

const server = require('../server')
const mongoose = require('mongoose')
const supertest = require('supertest')
const credits = {
  adm: {
    username: 'adm',
    password: 'pass'
  },
  mod: {
    username: 'mod',
    password: 'pass'
  },
  usr: {
    username: 'usr',
    password: 'pass'
  }
}

let adm = supertest.agent(server)
let mod = supertest.agent(server)
let usr = supertest.agent(server)

before(function (done) {
  mongoose.connection.on('open', done)
})

before(async function (done) {
  await adm.post('/api/login').send(credits.adm).expect(200)
  done()
})

before(async function (done) {
  await mod.post('/api/login').send(credits.mod).expect(200)
  done()
})

before(async function (done) {
  await usr.post('/api/login').send(credits.usr).expect(200)
  done()
})

describe('Lists', () => {
  it('GET lists', async function (done) {
    await adm.get('/api/lists')
      .expect(200)
      .expect(resp => {
        if (!Object.keys(resp.data).length) throw new Error('Excess data')
      })
    done()
  })
})

Here's an error:

Error: ECONNREFUSED: Connection refused
    at Test.assert (D:\OSPanel\node\deps\node_modules\supertest\lib\test.js:165:15)
    at assert (D:\OSPanel\node\deps\node_modules\supertest\lib\test.js:131:12)
    at D:\OSPanel\node\deps\node_modules\supertest\lib\test.js:128:5
    at Test.Request.callback (D:\OSPanel\node\deps\node_modules\superagent\lib\node\index.js:718:3)
    at ClientRequest.req.once.err (D:\OSPanel\node\deps\node_modules\superagent\lib\node\index.js:646:10)
    at Object.onceWrapper (events.js:255:19)
    at ClientRequest.emit (events.js:160:13)
    at Socket.socketErrorListener (_http_client.js:389:9)
    at Socket.emit (events.js:160:13)
    at emitErrorNT (internal/streams/destroy.js:64:8)
    at process._tickCallback (internal/process/next_tick.js:152:19)
jonathansamines commented 6 years ago

@Iworb To which host is your server bound to? If it is different than localhost/127.0.0.1, then that is likely what is causing your issue.

See https://github.com/visionmedia/supertest/issues/488#issuecomment-413094562 for more details.

sabyanna commented 3 years ago

I had the same error message, my bug was an incorrect url, i forgot the '/' at the beginning of the url.

alexandervandekleutab commented 3 years ago

@sabyanna this was the answer for me.

vukanac commented 2 years ago

Is it possible supertest to be the cause of the issue?

Error: ECONNREFUSED: Connection refused

Reproduce

var request = require('supertest');
var { expect } = require('chai');

var api = request('http://127.0.0.1:4000'); // <-- works
var api = request('http://localhost:4000'); // <-- does not work

describe('GET /home', () => {
  it('returns 200 status code', async () => {
    var res = await api
      .get('/any')
      .expect(200);
});

From terminal, both works:

$ curl http://localhost:4000/home
Welcome Home
$ curl http://127.0.0.1:4000/home
Welcome Home
vlad-at-work commented 2 years ago

Is it possible supertest to be the cause of the issue?

Error: ECONNREFUSED: Connection refused

Reproduce

  • Mac OS 10.15.7
  • node 18.3.0
  • chai@4.3.6
  • supertest@6.2.3
var request = require('supertest');
var { expect } = require('chai');

var api = request('http://127.0.0.1:4000'); // <-- works
var api = request('http://localhost:4000'); // <-- does not work
...
$ curl http://127.0.0.1:4000/home
Welcome Home

What I found was that you have to import express app and pass it to request(app) like so, otherwise you'd get the ECONN problem. I'm not totally sure why this is but I hope this helps someone.

Also, don't forget to then return the result of the (likely await) in the test function or else the test suite will complain at you: either return the promise or have a done(). Such were my meager findings.