[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

docs: clarify order of `before*` hooks cleanup functions (#10230)

authored by

Ari Perkkiö and committed by
GitHub
(May 3, 2026, 1:03 PM +0900) c99d18f8 4a07c25d

+124 -29
+4 -4
docs/api/hooks.md
··· 34 34 35 35 Here, the `beforeEach` ensures that user is added for each test. 36 36 37 - `beforeEach` can also return an optional cleanup function (equivalent to [`afterEach`](#aftereach)): 37 + `beforeEach` can also return an optional cleanup function. It's similar to [`afterEach`](#aftereach). The only difference is that it's executed after all other `afterEach` hooks: 38 38 39 39 ```ts 40 40 import { beforeEach } from 'vitest' ··· 43 43 // called once before each test run 44 44 await prepareSomething() 45 45 46 - // clean up function, called once after each test run 46 + // clean up function, called once after each test run, after afterEach hooks 47 47 return async () => { 48 48 await resetSomething() 49 49 } ··· 102 102 103 103 Here the `beforeAll` ensures that the mock data is set up before tests run. 104 104 105 - `beforeAll` can also return an optional cleanup function (equivalent to [`afterAll`](#afterall)): 105 + `beforeAll` can also return an optional cleanup function. It's similar to [`afterAll`](#afterall). The only difference is that it's executed after all other `afterAll` hooks: 106 106 107 107 ```ts 108 108 import { beforeAll } from 'vitest' ··· 111 111 // called once before all tests run 112 112 await startMocking() 113 113 114 - // clean up function, called once after all tests run 114 + // clean up function, called once after all tests run, after afterAll hooks 115 115 return async () => { 116 116 await stopMocking() 117 117 }
+15
docs/guide/lifecycle.md
··· 137 137 - `beforeEach` hooks execute (in order defined, or based on [`sequence.hooks`](/config/sequence#sequence-hooks)) 138 138 - Test function executes 139 139 - `afterEach` hooks execute (reverse order by default with `sequence.hooks: 'stack'`) 140 + - Cleanup functions returned from `beforeEach` hooks execute (reverse order by default with `sequence.hooks: 'stack'`) 140 141 - [`onTestFinished`](/api/hooks#ontestfinished) callbacks run (always in reverse order) 141 142 - If test failed: [`onTestFailed`](/api/hooks#ontestfailed) callbacks run 142 143 - Note: if `repeats` or `retry` are set, all of these steps are executed again 143 144 6. **[`afterAll`](/api/hooks#afterall) hooks:** Run once after all tests in the suite complete 145 + 7. **Cleanup functions returned from `beforeAll` hooks:** Run once after all tests in the suite complete 144 146 145 147 **Example execution flow:** 146 148 ··· 162 164 beforeAll(() => { 163 165 // Runs once before all tests in this suite 164 166 console.log('beforeAll') 167 + 168 + return function beforeAllCleanup() { 169 + // Runs once afterAll hooks have run 170 + console.log('beforeAllCleanup') 171 + } 165 172 }) 166 173 167 174 aroundEach(async (runTest) => { ··· 174 181 beforeEach(() => { 175 182 // Runs before each test 176 183 console.log('beforeEach') 184 + 185 + return function beforeEachCleanup() { 186 + // Runs after afterEach hooks have run 187 + console.log('beforeEachCleanup') 188 + } 177 189 }) 178 190 179 191 test('creates user', () => { ··· 206 218 // beforeEach 207 219 // test 1 208 220 // afterEach 221 + // beforeEachCleanup 209 222 // aroundEach after 210 223 // aroundEach before 211 224 // beforeEach 212 225 // test 2 213 226 // afterEach 227 + // beforeEachCleanup 214 228 // aroundEach after 215 229 // afterAll 230 + // beforeAllCleanup 216 231 // aroundAll after 217 232 ``` 218 233
+53 -14
test/unit/test/hooks-list.test.ts
··· 7 7 }, 8 8 }) 9 9 10 - const hookOrder: number[] = [] 10 + const hookOrder: string[] = [] 11 11 function callHook(hook: 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach', order: number) { 12 12 vitest[hook](() => { 13 - hookOrder.push(order) 13 + hookOrder.push(`${hook} #${order}`) 14 14 }) 15 15 } 16 16 17 17 describe('hooks are called as list', () => { 18 - callHook('beforeAll', 1) 18 + vitest.beforeAll(() => { 19 + hookOrder.push(`beforeAll #1`) 20 + 21 + return function beforeAllCleanup() { 22 + hookOrder.push(`beforeAllCleanup #1`) 23 + } 24 + }) 19 25 callHook('beforeAll', 2) 20 26 callHook('beforeAll', 3) 21 27 22 - callHook('afterAll', 4) 28 + callHook('afterAll', 1) 23 29 // will wait for it 24 30 vitest.afterAll(async () => { 25 31 await Promise.resolve() 26 - hookOrder.push(5) 32 + hookOrder.push(`afterAll #2`) 27 33 }) 28 - callHook('afterAll', 6) 34 + callHook('afterAll', 3) 35 + 36 + vitest.beforeEach(() => { 37 + hookOrder.push(`beforeEach #1`) 38 + 39 + return function beforeEachCleanup() { 40 + hookOrder.push(`beforeEachCleanup #1`) 41 + } 42 + }) 29 43 30 - callHook('beforeEach', 7) 31 - callHook('beforeEach', 8) 32 - callHook('beforeEach', 9) 44 + callHook('beforeEach', 2) 45 + callHook('beforeEach', 3) 33 46 34 - callHook('afterEach', 10) 35 - callHook('afterEach', 11) 36 - callHook('afterEach', 12) 47 + callHook('afterEach', 1) 48 + callHook('afterEach', 2) 37 49 38 50 test('before hooks pushed in order', () => { 39 - expect(hookOrder).toEqual([1, 2, 3, 7, 8, 9]) 51 + expect(hookOrder).toEqual([ 52 + 'beforeAll #1', 53 + 'beforeAll #2', 54 + 'beforeAll #3', 55 + 56 + 'beforeEach #1', 57 + 'beforeEach #2', 58 + 'beforeEach #3', 59 + ]) 40 60 }) 41 61 }) 42 62 43 63 describe('previous suite run all hooks', () => { 44 64 test('after all hooks run in defined order', () => { 45 - expect(hookOrder).toEqual([1, 2, 3, 7, 8, 9, 10, 11, 12, 4, 5, 6]) 65 + expect(hookOrder).toEqual([ 66 + 'beforeAll #1', 67 + 'beforeAll #2', 68 + 'beforeAll #3', 69 + 70 + 'beforeEach #1', 71 + 'beforeEach #2', 72 + 'beforeEach #3', 73 + 74 + 'afterEach #1', 75 + 'afterEach #2', 76 + 77 + 'beforeEachCleanup #1', 78 + 79 + 'afterAll #1', 80 + 'afterAll #2', 81 + 'afterAll #3', 82 + 83 + 'beforeAllCleanup #1', 84 + ]) 46 85 }) 47 86 })
+52 -11
test/unit/test/hooks-stack.test.ts
··· 7 7 }, 8 8 }) 9 9 10 - const hookOrder: number[] = [] 10 + const hookOrder: string[] = [] 11 11 function callHook(hook: 'beforeAll' | 'beforeEach' | 'afterAll' | 'afterEach', order: number) { 12 12 vitest[hook](() => { 13 - hookOrder.push(order) 13 + hookOrder.push(`${hook} #${order}`) 14 14 }) 15 15 } 16 16 17 17 describe('hooks are called sequentially', () => { 18 - callHook('beforeAll', 1) 19 - callHook('afterAll', 4) 18 + vitest.beforeAll(() => { 19 + hookOrder.push(`beforeAll #1`) 20 20 21 + return function beforeAllCleanup() { 22 + hookOrder.push(`beforeAllCleanup #1`) 23 + } 24 + }) 21 25 callHook('beforeAll', 2) 26 + callHook('afterAll', 1) 27 + 28 + callHook('beforeAll', 3) 22 29 // will wait for it 23 30 vitest.afterAll(async () => { 24 31 await Promise.resolve() 25 - hookOrder.push(5) 32 + hookOrder.push(`afterAll #2`) 26 33 }) 27 34 28 - callHook('beforeEach', 7) 29 - callHook('afterEach', 10) 35 + vitest.beforeEach(() => { 36 + hookOrder.push(`beforeEach #1`) 30 37 31 - callHook('beforeEach', 8) 32 - callHook('afterEach', 11) 38 + return function beforeEachCleanup() { 39 + hookOrder.push(`beforeEachCleanup #1`) 40 + } 41 + }) 42 + 43 + callHook('beforeEach', 2) 44 + callHook('afterEach', 1) 45 + 46 + callHook('beforeEach', 3) 47 + callHook('afterEach', 2) 33 48 34 49 test('before hooks pushed in order', () => { 35 - expect(hookOrder).toEqual([1, 2, 7, 8]) 50 + expect(hookOrder).toEqual([ 51 + 'beforeAll #1', 52 + 'beforeAll #2', 53 + 'beforeAll #3', 54 + 55 + 'beforeEach #1', 56 + 'beforeEach #2', 57 + 'beforeEach #3', 58 + ]) 36 59 }) 37 60 }) 38 61 39 62 describe('previous suite run all hooks', () => { 40 63 test('after all hooks run in reverse order', () => { 41 - expect(hookOrder).toEqual([1, 2, 7, 8, 11, 10, 5, 4]) 64 + expect(hookOrder).toEqual([ 65 + 'beforeAll #1', 66 + 'beforeAll #2', 67 + 'beforeAll #3', 68 + 69 + 'beforeEach #1', 70 + 'beforeEach #2', 71 + 'beforeEach #3', 72 + 73 + 'afterEach #2', 74 + 'afterEach #1', 75 + 76 + 'beforeEachCleanup #1', 77 + 78 + 'afterAll #2', 79 + 'afterAll #1', 80 + 81 + 'beforeAllCleanup #1', 82 + ]) 42 83 }) 43 84 })