I am practicing basic unit test cases with mocha
and a bit confused HOW and WHEN to use done() handler.
done()
?Below is my sample code where I am not able to use done
:
it('Testing insertDocumentWithIndex', async (done) => {
try{
var data = await db.insertDocumentWithIndex('inspections', {
"inspectorId" : 1,
"curStatus" : 1,
"lastUpdatedTS" : 1535222623216,
"entryTS" : 1535222623216,
"venueTypeId" : 1,
"location" : [
45.5891279,
-45.0446183
]
})
expect(data.result.n).to.equal(1);
expect(data.result.ok).to.equal(1);
}
catch(e){
logger.error(e);
done(e);
}
})
When I run, it fails and throws an error-
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
But done
should be called in case of failure only(Please correct me If I am missing something, I am a beginner😄), which I have done in catch
block and coming to the second point of returning a Promise, well that works fine. See below code
it('Testing insertDocumentWithIndex', async () => {
return new Promise(async (resolve, reject) => {
try{
var data = await db.insertDocumentWithIndex('inspections', {
"inspectorId" : 1,
"curStatus" : 1,
"lastUpdatedTS" : 1535222623216,
"entryTS" : 1535222623216,
"venueTypeId" : 1,
"location" : [
45.5891279,
-45.0446183
]
})
expect(data.result.n).to.equal(1);
expect(data.result.ok).to.equal(1);
resolve()
}
catch(e){
reject(e);
}
})
});
But this requires an additional Promise construction code which is antipattern. But it raises another question
done
should be used ?Any help or suggestion for a better approach for writing test cases with mocha
will help.
This argument is a function, and is usually called done by convention. This signals to Mocha that what we're doing inside of before() runs asynchronously, and tells it to wait until we call done() to start running the tests.
Writing Asynchronous Tests with Mocha. To indicate that a test is asynchronous in Mocha, you simply pass a callback as the first argument to the it() method: it('should be asynchronous', function(done) { setTimeout(function() { done(); }, 500); });
Create a file named teams. js, import the API using require and create the function getTeamByPlayer it will return a promise, using setTimeout simulate the async process. Our promise return the resolve if the team with the player is found or the reject with an error if not found. Export the function to be used.
The keyword await is used to wait for a Promise. It can only be used inside an async function. This keyword makes JavaScript wait until that promise settles and returns its result.
The correct way is to not use done
with async..await
. Mocha supports promises and is able to chain a promise that is returned from it
, etc. functions. And async
function is syntactic sugar for a function that always returns a promise:
it('Testing insertDocumentWithIndex', async () => {
var data = await db.insertDocumentWithIndex('inspections', {
"inspectorId" : 1,
"curStatus" : 1,
"lastUpdatedTS" : 1535222623216,
"entryTS" : 1535222623216,
"venueTypeId" : 1,
"location" : [
45.5891279,
-45.0446183
]
})
expect(data.result.n).to.equal(1);
expect(data.result.ok).to.equal(1);
})
done
is needed only for testing asynchronous APIs than don't involve promises. Even then, converting to promises often results in cleaner control flow.
And this
it('Testing insertDocumentWithIndex', async () => {
return new Promise(async (resolve, reject) => {
...
is promise construction antipattern, which is even worse because of async
promise constructor callback.
These concerns also apply to other JS testing frameworks with similar API, Jest and Jasmine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With