TypeError when calling this.timeout() inside an arrow function test in Mocha
0 reputation · 11 Dec 2023, 07:15 UTC
0 reputation · 11 Dec 2023, 07:15 UTC
I am configuring per-test timeouts in Mocha and hit a failure when adjusting the timeout dynamically. In a test written with an arrow function, calling this.timeout(5000) throws a TypeError because this is not the Mocha test context. The same call works in a test declared with a regular function expression.
My constraints: some suites were migrated to arrow functions for stylistic consistency, and I would prefer not to rewrite every test back to function expressions. I also need long-running async tests (around 3–5 seconds) to pass without raising the global --timeout for the whole suite, since the default 2000ms limit otherwise fails them. I am aware that setting the timeout to 0 disables the limit entirely, which risks hanging our CI pipeline if a test deadlocks, so that is not an acceptable fallback.
Assuming a current Mocha version (this should be verified against the release in use):
this context?this.timeout() in a describe callback reliably propagate to nested hooks and tests, or do hooks have separate timeout behavior?34775 reputation · 11 Dec 2023, 13:23 UTC
In Mocha, this.timeout() relies on the test‑suite context object that is bound to the function executing the test or hook. Arrow functions do not create their own this binding; they inherit this from the surrounding scope, which is usually the module exports object. Consequently, calling this.timeout(5000) inside an arrow‑function test throws a TypeError: this.timeout is not a function.
it() (or describe()) and treats it as the per‑test (or per‑suite) limit, independent of this.this.timeout() is called inside a regular‑function describe callback, the value becomes the default timeout for all tests and hooks (beforeEach, afterEach, before, after) defined within that suite, unless they explicitly override it.timeout property in a Mocha configuration file (.mocharc.js, mocharc.json, or mocha.opts) is functionally identical to the CLI flag --timeout; it sets the global default that can be overridden at the suite or test level.it:it('should complete within 5 seconds', () => {
// async work that may take up to ~5 s
return new Promise(resolve => setTimeout(resolve, 4500));
}, 5000);
describe block:describe('suite with arrow tests', function () {
// regular function so `this` is the Mocha context
this.timeout(3000); // default for this suite
it('quick test', () => { return Promise.resolve(); });
it('longer test', () => { return new Promise(r => setTimeout(r, 2500)); }); // uses suite default
});
// .mocharc.json
{
"timeout": 3000
}
mocha --timeout 3000.this.timeout() in a regular‑function describe or via config).beforeEach, etc.) does **not** inherit a test‑level timeout set via the third argument; it only receives the suite default unless you set it explicitly on the hook.Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.