Test Registered After Collection
ID |
javascript.async_test_registration |
Severity |
critical |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Reliability |
Language |
JavaScript |
Tags |
async, reliability, testing |
Description
Reports an it(…) or test(…) declared from inside an async callback or a .then() continuation.
Every JavaScript runner collects a file’s tests synchronously: it runs the module and the suite callbacks once, records the declarations it saw, then starts executing them. A declaration that happens after the first await, or in a continuation that resolves on a later turn of the event loop, happens after collection has closed.
The whole chain of enclosing functions is examined, so a test nested several callbacks deep inside an async suite is reported too. The test’s own callback may of course be async — that is the ordinary way to write an asynchronous test and is never reported.
Rationale
// Bad
describe('rates', async () => {
const rates = await loadRates();
it('converts euros', () => { // collected too late, never runs
expect(convert(rates, 10)).toBe(12);
});
});
-
The suite is quietly smaller than the file: the runner reports the tests it collected and says nothing about the ones it did not.
-
Depending on the runner the test is dropped silently, or the run fails late with "cannot add a test after tests have started" — neither points at the
asynckeyword that caused it. -
The assertions inside the declaration protect nothing, while the file keeps reading as though they did.
-
Adding tests beside it makes the problem worse without making it visible, because they are lost the same way.