84

I'm starting with tests in Node. Using mocha, chai and nock (to intercept external HTTP api calls).

I have written 3 tests, all of them are a pass, however, when I added the 3rd test, mocha stopped exiting after running the tests, with no error or indication of anything wrong.

If I comment the 3rd test, mocha exits just fine.

This is the test causing the 'issue':

describe('tokenizer.processFile(req, \'tokenize\')', () => {

    it('should tokenize a file', async () => {

        req = {
            file: {
                originalname: 'randomcards.txt',
                buffer: cardsFile_buffer
            },
            user: {
                displayName: user
            }
        };

        expect(Buffer.from(await tokenizer.processFile(req, 'tokenize'))).to.deep.equal(tokensFile_buffer);

    });

});

Again, that test is a pass, which baffles me.

Here's the code of tokenizer.processFile:

processFile: function(req, whatTo){

        combinedLogger.info(`Request to ${whatTo} ${req.file.originalname} received. Made by: ${req.user.displayName}`);

        return new Promise(function(resolve, reject){

            const lines = [], responses = [];

            const lineReader = require('readline').createInterface({
                input: require('streamifier').createReadStream(req.file.buffer)
            });

            lineReader.on('line', line => {
                lines.push(line);
            });

            lineReader.on('close', async () => {

                //process every line sequentially

                try {

                    //ensure DB connected to mass insert
                    await db_instance.get_pool();

                    for(const line of lines) {
                        var response;
                        req.current_value = line;
                        if (whatTo == 'tokenize'){

                            response = await Tokenize(line);
                            db_instance.insertAction(req, 'tokenize', response);
                        }
                        else if (whatTo == 'detokenize'){
                            combinedLogger.info(`Request to detokenize ${line} received. Made by: ${req.user.displayName}`);
                            response = await Detokenize(line);
                            db_instance.insertAction(req, 'detokenize', line);
                        }
                        responses.push(response);
                    }

                    resolve(responses.join("\r\n"));

                }
                catch(error){
                    reject(error);
                }
            });

        });

    }

Functions Tokenize(value) and Detokenize(value) are also called in the other 2 tests, which when run, mocha exits just fine.

Any idea what's causing this?

Mocha version: 5.1.1

Fede E.
  • 2,118
  • 4
  • 23
  • 39

1 Answers1

162

I know it is a bit late to answer this, but I was facing a similar problem and saw your post.

In mocha 4.0.0, they changed the behavior of tests on finalization.From here:

If the mocha process is still alive after your tests seem "done", then your tests have scheduled something to happen (asynchronously) and haven't cleaned up after themselves properly. Did you leave a socket open?

In your case, it seems like a call to createReadStream() was never closed.

So, you have 2 options:

Option A: Close the fs and other streams open (recommended)

Option B: Run mocha with the --exit option.

Alex Mantaut
  • 3,657
  • 3
  • 35
  • 45
  • ... how does one wait till all tests are done? My issue is I start a mongodb connection in my --delay function... By there is no onTestsDone event... – Ray Foss Nov 08 '19 at 14:37
  • @RayFoss, I think in that case you need to use the done() method, to indicate that your test case has finished... Check: https://medium.com/caffeine-and-testing/async-testing-with-mocha-with-callbacks-and-promises-5d0002661b3f – Alex Mantaut Nov 10 '19 at 21:55
  • 15
    This behavior can be really helpful, and I wouldn't recommend forcing your tests to exit. Usually when mocha hangs and won't exit, there is something in your code that needs to be cleaned up. It's better to find the problem. I've found a lot of potential leaks this way. – reads0520 Jan 17 '20 at 19:22
  • So what if a test is just hanging and I'm not using `createReadStream`? – Andrew Koster May 23 '20 at 02:53
  • 7
    I used https://www.npmjs.com/package/why-is-node-running to find out why my node application was still running. – Martin P. Oct 05 '20 at 20:41
  • 3
    Do not force close or defeat this behavior. In my case, the MongoDB driver was left open and that ended up keeping the test running like @reads0520 mentioned. – Manabu Tokunaga Jun 10 '21 at 23:16
  • For me it was a [`setInterval(() => {})`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) that kept Mocha running. Maybe it helps somebody else. – adriaan Jun 28 '22 at 09:04
  • This answer is correct, and @reads0520 is right too. Find out what resources you are leaving open. For me it was the `ioredis` library: the solution was to add an `after` block (outside of all my tests) to call the `.teardown()` method on the object that holds the connection to redis. I used https://www.npmjs.com/package/wtfnode to identify the leak, it worked great. – cobbzilla Aug 30 '22 at 15:16