afterEach called multiple times when there is an error in an inner suite · Issue #3105 · mochajs/mocha · GitHub
More Web Proxy on the site http://driver.im/
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Checked next-gen ES issues and syntax problems by using the same environment and/or transpiler configuration without Mocha to ensure it isn't just a feature that actually isn't supported in the environment in question or a bug in your code.
'Smoke tested' the code to be tested by running it outside the real test suite to get a better sense of whether the problem is in the code under test, your usage of Mocha, or Mocha itself
Ensured that there is no discrepancy between the locally and globally installed versions of Mocha. You can find them with: node node_modules/.bin/mocha --version(Local) and mocha --version(Global). We recommend avoiding the use of globally installed Mocha.
Description
When you have a nested suite that throws an error, the afterEach in the outer suite may be called twice and/or called in the middle of the inner afterEach.
Steps to Reproduce
Create an outer suite with an inner suite.
Add a test in the inner suite.
Add afterEach hook in both suites.
Add some async calls.
Throw an error after the test ended but before the inner afterEach ended.
Example:
const bluebird = require("bluebird");
describe("outer tests", () => {
afterEach(async () => {
console.log("outer afterEach started");
bluebird.delay(1000);
console.log("outer afterEach ended");
});
function doSomething(cb) {
fs.exists("temp.sh", () => {
cb();
setTimeout(() => {
// This error is thrown after test was ended but before the inner afterEach ended.
// it will trigger the outer afterEach
throw new Error();
}, 100);
});
}
describe("inner tests", function () {
afterEach(async () => {
console.log("inner afterEach started");
await bluebird.delay(1000);
console.log("inner afterEach ended");
});
it("should do something", function (done) {
doSomething(() => {
done();
});
})
});
});
Expected behavior:
Outer afterEach is called once and only after inner AfterEach ended.
Actual behavior: [What actually happens]
Outer AfterEach is called before inner AfterEach ended. If you play with the delays you might see that sometimes the outer AfterEach is called twice, but it is hard to reproduce.
I think what is happening here is much simpler than the example makes it look...
The test tells Mocha's it's passed (done()), but has left an asynchronous action running that will later fail. Note that this would be the same if the test was completely synchronous (no promise or done callback) and started the same asynchronous throwing action.
Since the afterEach's asynchronous code is not what actually failed, it is still running -- effectively a fractal pattern of the same issue: Mocha doesn't intercept asynchronous actions, doesn't track which are from which tests/hooks and if you tell Mocha that something is passed/failed (e.g. by throwing an asynchronous exception in step 2) then it will not stop the other asynchronous work that was started by that test or hook and is still running.
Because the hook completes via promise after (as far as Mocha can tell) failing via asynchronous exception (from the test, per step 2), Mocha is told the hook completes twice, which triggers duplicate end-summary output as in Duplicated failing test summary #2906 (with an additional error reported about the double-completion of the hook)
Closing this as a duplicate of #967 and duplicate of #2906, but feel free to weigh in on either or both of those issues!
Prerequisites
common mistake
labelnode node_modules/.bin/mocha --version
(Local) andmocha --version
(Global). We recommend avoiding the use of globally installed Mocha.Description
When you have a nested suite that throws an error, the afterEach in the outer suite may be called twice and/or called in the middle of the inner afterEach.
Steps to Reproduce
Example:
Output:
Expected behavior:
Outer afterEach is called once and only after inner AfterEach ended.
Actual behavior: [What actually happens]
Outer AfterEach is called before inner AfterEach ended. If you play with the delays you might see that sometimes the outer AfterEach is called twice, but it is hard to reproduce.
Reproduces how often:
Always
Versions
mocha - 4.0.1
node - 6.12.0
OS - ubuntu 17.10 x64
Shell - bash
typescript 2.3.4
Additional Information
The text was updated successfully, but these errors were encountered: