5

I would like to test async codes with Mocha.

I followed this tutorial testing-promises-with-mocha. In the end, it says the best way is async/await.

Following is my code, I intended to set setTimeout longer than Mocha default.

describe('features', () => {
  it('assertion success', async() => {
    const resolvingPromise = new Promise( resolve => {
      setTimeout(() => {
        resolve('promise resolved')
      }, 3000)
    })

    const result = await resolvingPromise
    expect(result).to.equal('promise resolved')
  })
})

Mocha give me error as following:

Error: Timeout of 2000ms exceeded. For async tests and hooks, 
ensure "done()" is called; if returning a Promise, ensure it resolves...

How to resolve the error? Simple set mocha --timeout 10000 longer?

Thanks for your time!

Mocha: 5.2.0
Chai: 4.2.0
mCY
  • 2,625
  • 4
  • 14
  • 21

3 Answers3

2

as you mentioned, --timeout flag does the job.

node ./node_modules/mocha/bin/mocha --timeout <milliseconds>

you can also check: Change default timeout for mocha if you want to set default timeout in whole project.

miksa
  • 21
  • 2
-2

For async tests you should invoke the done() callback.

describe('features', () => {
  it('assertion success', async(done) => { // pass done here
    const resolvingPromise = new Promise( resolve => {
      setTimeout(() => {
        resolve('promise resolved')
      }, 3000)
    })

    const result = await resolvingPromise
    expect(result).to.equal('promise resolved')
    done() // invoke at end
  })
})
Dinesh Pandiyan
  • 5,814
  • 2
  • 30
  • 49
-2

Mocha has timeout controls. Mocha docs

Syntax is:

it('should take less than 500ms', function(done) {
  this.timeout(5000); // 5 seconds
  setTimeout(done, 3000);
});

Your example:

describe('features', () => {
  it('assertion success', async (done) => {
    this.timeout(5000);
    const resolvingPromise = new Promise(resolve => {
      setTimeout(() => resolve('promise resolved'), 3000)
    });

    const result = await resolvingPromise();
    expect(result).to.equal('promise resolved');
    done();
  });
});
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • but some steps really take long time to finish. It's not very good to give them a very large timeout right ? – mCY Dec 28 '18 at 07:59
  • This will only change the test timeout. `done()` is added to the end of your test. Do you mean some steps are just computationally complex and long, or are you testing code that is making API/network requests? If you're testing code that contains steps that take a long time, increasing the timeout is the best option. If testing code making external requests, then those API/network requests should be stubbed. If you're testing code that itself has long timers, then use a library like sinon or similar that mocks and controls the system timer so you manually control ticks. – Drew Reese Dec 28 '18 at 08:09
  • Thanks Drew Reese for the information! I'm doing backend testing. Our dev server is in google cloud. So Basically I need to send requests to remote server. I don't want to mock in the test. Some requests are really long to response. I want to avoid this error by adding `done()` to somewhere as it suggested. Because I think adjust timeout is not the best way? Or in this case, I just have to increase timeout? – mCY Dec 28 '18 at 08:21
  • You'll need to extend the default timer as well as adding done to your asynchronous tests, that is if the default 2000ms timer prematurely fails your tests. – Drew Reese Dec 28 '18 at 08:24