Vitest `threads: true` global state leakage with `isolate: false`
0 reputation · 27 Nov 2022, 17:04 UTC
0 reputation · 27 Nov 2022, 17:04 UTC
Vitest users running test suites with threads: true and isolate: false in versions supporting parallel execution may observe non-deterministic test outcomes when suites depend on shared global state. The precise goal is to determine how parallel test processes reconcile module initialization and global variable persistence across worker threads without full process isolation.
Constraints and uncertainty involve the degree to which module hoisting, event-loop timing, and custom reporter instrumentation contribute to state leakage. Diagnostics that do not register as formal test failures may still be affected, complicating root-cause analysis in large codebases.
Does setting isolate: true eliminate the observed non-determinism, and what are the performance trade-offs? Which lifecycle hooks or global setup functions are most vulnerable to cross-process state interference? Can custom reporters reliably distinguish between intended test assertions and side-effects introduced by thread interaction?
33275 reputation · 27 Nov 2022, 17:39 UTC
Setting isolate: true in Vitest eliminates the non‑determinism caused by shared global state when threads: true is used.
With threads: true and isolate: false Vitest re‑uses the same V8 context across worker threads. Top‑level module code runs once, so any variables, singletons, or side‑effects created at module scope are shared. Consequently, beforeAll/afterAll hooks defined in setup files and globals mutated in beforeEach/afterEach are visible to all workers, producing order‑dependent test results.
The non‑determinism appears as tests passing in isolation but failing when run in parallel because the shared state accumulates or is reset inconsistently across workers. Event‑loop timing and custom reporter instrumentation can exacerbate the issue but are not the root cause.
vitest.config.ts (or vitest.config.js) to set isolate: true while keeping threads: true:import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
threads: true,
isolate: true,
// optional: limit workers to CPU count
// poolOptions: { threads: { isolated: true } }
}
})
beforeEach hook or moved to a dedicated fixture that is reset per test.isolate: truebeforeAll / afterAll hooks defined in setupFiles or within test files.beforeEach / afterEach that are not reset per test (e.g., counters, caches, fake timers).No, unless the reporter runs exclusively in the main thread or snapshots the global state before each worker execution. A reporter that reads or writes shared globals cannot reliably tell whether a change originates from a test assertion or from another worker's leakage.
If you are using a Node.js version older than v14.8, worker‑thread isolation may be incomplete; confirming your Node version would change the recommendation to upgrade Node before relying on isolate: true.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.