Testing with mocha times out on failed assert
mrfitz42 opened this issue · 9 comments
While unit testing legacy code which uses async and callbacks, no ESM or Promises, I noticed that many tests that failed an assert would hang and timeout rather that displaying the failure. Code has been upgraded to use the latest non-ESM-only package versions. I narrowed down the issue to tests that open a database connection.
I am not sure if this is a oracledb issue or a mocha issue, but I thought I would start here since the assert failure generates the following error message in node:
node:internal/process/promises:289
triggerUncaughtException(err, true /* fromPromise */);
^
While mocha's timeout mentions:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (oracledb-mocha.test.js)
- What versions are you using?
database version: Oracle 19c Enterprise edition version 19.21.0.0.0
process.platform: 'linux'
process.version: 'v20.11.0'
process.arch: 'x64'
require('oracledb').versionString: '6.5.1'
require('oracledb').oracleClientVersionString: undefined
- Is it an error or a hang or a crash?
Hangs on failed assert()
- What error(s) or behavior you are seeing?
$ mocha oracledb-mocha.test.js
Running in thick mode
investigating
when opening a connection
Obtained connection
Releasing connection - no error
connection: Connection {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
_dbObjectClasses: Map(0) {},
_closing: false,
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false
}
1) should fail an assert without hanging
0 passing (2s)
1 failing
1) investigating
when opening a connection
should fail an assert without hanging:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/mikef/APEX/spoccode-apex/oracledb-mocha.test.js)
at listOnTimeout (node:internal/timers:573:17)
at process.processTimers (node:internal/timers:514:7)
$ node oracledb-mocha.test.js
Running in thick mode
Obtained connection
Releasing connection - no error
connection: Connection {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
_dbObjectClasses: Map(0) {},
_closing: false,
[Symbol(shapeMode)]: false,
[Symbol(kCapture)]: false
}
node:internal/process/promises:289
triggerUncaughtException(err, true /* fromPromise */);
^
AssertionError [ERR_ASSERTION]: expected failed assert
at /home/mikef/APEX/spoccode-apex/oracledb-mocha.test.js:29:7
at /home/mikef/APEX/spoccode-apex/node_modules/oracledb/lib/util.js:136:7 {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
}
Node.js v20.11.0
- Include a runnable Node.js script that shows the problem.
var oracledb = require('oracledb');
var assert = require('assert');
// Optionally run in node-oracledb Thick mode
if (process.env.NODE_ORACLEDB_DRIVER_MODE === 'thick') {
oracledb.initOracleClient(); // enable node-oracledb Thick mode
}
console.log(oracledb.thin ? 'Running in thin mode' : 'Running in thick mode');
var test_function = function(next) {
var connAttrs = {
user: process.env.NODE_ORACLEDB_USER,
password: process.env.NODE_ORACLEDB_PASSWORD,
connectString: process.env.NODE_ORACLEDB_CONNECTIONSTRING,
};
oracledb.getConnection(connAttrs, function(err, conn) {
if (err) {
console.log('Error from getConnection:', err);
return next(err);
}
console.log('Obtained connection');
conn.close(function(err) {
console.log('Releasing connection', err || '- no error');
assert(!err, 'threw an error');
console.log('connection:', conn);
assert(!conn, 'expected failed assert');
next();
});
});
};
if (require.main === module) {
test_function(() => process.exit());
}
else {
describe('investigating', function() {
context('when opening a connection', function() {
it('should fail an assert without hanging', function(done) {
test_function(done);
});
});
});
}
@mrfitz42 This is a mocha error.
To run a mocha test with any node-oracledb functionality, we usually use mocha <testfilename> --t 0
, to ensure that there are no timeouts.
Please check our https://github.com/oracle/node-oracledb/blob/main/test/opts/.mocharc.yaml file to check the test configuration settings in mocha for the node-oracledb tests provided in this repo.
The reason that hang might be happening, is because the connection is not explicitly closed, after the error is thrown and the program takes its time to close the connections.
Running mocha oracledb-mocha.test.js --t 0
doesn't hang, but it also does not show the failed assert ... it exits mocha without any test status.
What do you mean by "the connection is not explicitly closed" when the test calls conn.close(function(err) { ... });
with the assert in the callback function?
@mrfitz42 My apologies. On second look, I realise that connection.close
function is called and the assert fail is in the callback function.
We will look at it and let you know.
I can see the assert
hangs or abnormally terminates.
As a workaround, can you use try/catch something like this? or just an if stmts
try {
assert(!conn, 'expected failed assert');
} catch (err) {
return next(err);
}
It still needs to be investigated if this is something related to mocha and async functions returning a promise..
If you are using old-style callbacks you cannot throw exceptions. You must always call the done
function when you are finished. If you want to throw exceptions you will have to catch them yourself as @sudarshan12s demonstrated. This is a "feature" and has nothing to do with the driver!
Well that's annoying. Is there any way of resolving the pending promise in the callback rather than wrapping try-catch around the asserts? If wrapping the asserts is the only way, I'll have to change about 1500 unit tests.
I see some workarounds like this might help
let unhandledRejectionExitCode = 0;
process.on("unhandledRejection", (reason) => {
console.log("unhandled rejection:", reason);
unhandledRejectionExitCode = 1;
throw reason;
});
or
mocha --unhandled-rejections=strict test/checkconnhang.js --t 0
Thank you very much. Adding --unhandled-rejections=strict
to the mocha command line did the trick.
I appreciate all your help in solving what turned out to be a mostly mocha issue.
Closing this as this is not a node-oracledb issue