Limits of Mocha's --delay option for async test suites
0 reputation · 07 May 2020, 16:26 UTC
0 reputation · 07 May 2020, 16:26 UTC
The --delay command-line option is documented to queue test definitions so that execution waits until the suite's run() method is invoked. This behavior is well-defined for synchronous test functions, but the boundary becomes unclear when tests are declared as async. In suites that mix synchronous and asynchronous definitions, the async test bodies may execute immediately upon registration rather than waiting for run(), which undermines the deferred execution model.
This ambiguity is version-sensitive across Mocha 8.x, 9.x, and 10.x, and the official CLI documentation does not explicitly state whether --delay is intended to support async test functions. Developers migrating existing suites or building new ones face uncertainty about whether to rely on --delay for async definitions or adopt alternative patterns. The lack of a clear specification makes it difficult to determine if immediate async execution is a supported limitation or an unintended side effect.
Is the immediate execution of async test bodies under --delay an intentional limitation or an undocumented behavior in current Mocha releases? What is the supported approach for deferring async test definitions without wrapping them in synchronous functions? Does the Mocha documentation or changelog clarify the exact interaction between --delay and async test functions?
32275 reputation · 07 May 2020, 21:06 UTC
The immediate execution of async test bodies under --delay is a longstanding, expected limitation across Mocha 8.x, 9.x, and 10.x, not an undocumented bug. --delay postpones the root suite's run loop and pending hooks; it does not intercept the registration phase where test callbacks are invoked. When Mocha loads a test file, it walks the suite tree and calls each test function to capture its return value. For an async function, that call starts the promise chain immediately, so any await, timer, or I/O inside the body begins before run() is invoked.
The following are well-established from Mocha's documented interface:
--delay is documented as delaying root suite execution, with no mention of special handling for async functions.require.run().--delay, indicating the limitation is longstanding rather than a recent regression.The precise source-level mechanism is consistent with observed behavior, though exact implementation details should be verified against your installed version. This summary reflects documented behavior and long-standing community understanding across Mocha 8–10; check the changelog for your exact build if you are on a patched or pre-release version.
Mocha does not provide a supported way to defer async test definitions without synchronous indirection. The --delay flag is scoped to the run loop, not registration. If async setup must wait for an explicit trigger, move it into a root before hook, which is deferred because hooks are part of the runnable suite. Alternatively, generate tests inside a synchronous describe callback and call run() from your own bootstrap logic. Wrapping the async body in a synchronous factory that returns an async function is the closest pattern, but it still requires a synchronous outer function at registration time.
mocha --delay ./test.js and observe that the async log appears before the delayed start message.--delay and confirm both tests log after the runner starts.If the async work is in top-level await during file loading rather than inside an it() callback, state that explicitly. Top-level await executes before Mocha can apply any delay, which changes the recommendation from a wrapper pattern to restructuring the file load.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.