For AI agents: the complete documentation index is available at https://rstest.rs/llms.txt, the full documentation bundle is available at https://rstest.rs/llms-full.txt, and this page is available as Markdown at https://rstest.rs/config/test/isolate.md.
close
  • English
  • isolate

    • Type: boolean
    • Default: true
    • CLI: --isolate, --isolate=false, --no-isolate

    Control isolation between test files. By default, each file gets its own module state and test environment, preventing state from one file from affecting another.

    Tests within the same file still share that file's environment. Use beforeEach and afterEach to reset state between individual tests.

    For forks and threads, setting isolate: false lets files in the same worker reuse module caches and the test environment. This can improve performance if the files do not leave state behind.

    Isolation does not control parallelism. Use pool.maxWorkers to limit Node.js test workers and maxConcurrency to limit concurrent test cases within a file.

    Info

    vmForks and vmThreads always isolate test files This option has no effect when pool.type is vmForks or vmThreads. Rstest reuses the worker but creates a fresh VM context, module graph, and test environment for every file. Setup files and worker-scoped fixtures therefore also remain file-scoped.

    Shared state when isolation is disabled

    For forks and threads, isolate: false has these consequences:

    • A module imported by several files is evaluated once per worker. Hooks registered at the top level of a shared helper are therefore registered only for the first file that imports it.
    • setupFiles still runs before every test file. Put shared hook registration and per-file resets there.
    • The test environment is reused within each worker. DOM state, uncleared timers, and installed fake timers can persist across files; reset them explicitly if later files depend on a clean environment.
    CLI
    rstest.config.ts
    npx rstest --no-isolate

    Module mocks

    Because modules are shared across the files in a worker, a module mock behaves differently when isolate is false:

    • The mock may not apply. If an earlier file already loaded a module that imports the mocked one, that cached module keeps the real implementation.
    • The mock may leak. Modules loaded while the mock is active keep the mocked implementation in later files.

    Which file fails depends on the order in which files run.

    For example, both test files below import ./user-service, which calls fetchUser() from ./api. The real fetchUser() returns { name: 'Bob' }, and only user-service.test.ts mocks it. To keep both files correct in any order, the mocking file resets the module cache before importing the code under test, then undoes the mock after it finishes (highlighted lines):

    user-service.test.ts
    import { afterAll, expect, rs, test } from '@rstest/core';
    import { loadUserName } from './user-service';
    
    rs.hoisted(() => {
      rs.resetModules();
    });
    
    rs.mock('./api', () => ({ fetchUser: () => ({ name: 'Alice' }) }));
    
    afterAll(() => {
      rs.doUnmock('./api');
      rs.resetModules();
    });
    
    test('loads the mocked user name', () => {
      expect(loadUserName()).toBe('Alice');
    });
    profile.test.ts
    import { expect, test } from '@rstest/core';
    import { loadUserName } from './user-service';
    
    test('loads the real user name', () => {
      expect(loadUserName()).toBe('Bob');
    });

    profile.test.ts needs no changes: whether it runs before or after user-service.test.ts, it gets the real ./api.

    • Call rs.resetModules() inside rs.hoisted() so the module cache is cleared before the static imports run.
    • Call rs.doUnmock() in afterAll for every module the file mocks.
    • Both rs.resetModules() calls clear the shared module cache, so modules are re-evaluated for this file and for the next file in the worker. Files without this pattern keep sharing modules.