isolate
- 类型:
boolean - 默认值:
true - CLI:
--isolate,--isolate=false,--no-isolate
控制测试文件之间的隔离。默认情况下,每个文件有独立的模块状态和测试环境,避免一个文件的状态影响另一个文件。
同一文件中的测试仍然共享该文件的环境。需要在单个测试之间重置状态时,请使用 beforeEach 和 afterEach。
对于 forks 和 threads,设置 isolate: false 后,同一 worker 中的文件可以复用模块缓存和测试环境。如果文件不会留下影响后续测试的状态,这样可以提升性能。
隔离不控制并行数量。限制 Node.js 测试 worker 数量请使用 pool.maxWorkers,限制文件内并发测试用例数量请使用 maxConcurrency。
vmForks 和 vmThreads 始终按文件隔离
当 pool.type 为 vmForks 或 vmThreads 时,此选项不生效。Rstest 会复用 worker,但会为每个文件创建新的 VM context、module graph 和 test environment。因此,setup 文件和 worker scope fixture 也仍保持文件级生命周期。
对于 forks 和 threads,设置 isolate: false 后:
- 多个文件引入同一模块时,该模块每个 worker 只执行一次。因此,在共用 helper 顶层注册的 hook 只会对第一个引入它的文件生效。
setupFiles仍会在每个测试文件执行前运行。共用 hook 的注册和按文件重置状态的逻辑应放在这里。- 同一 worker 会复用测试环境。DOM 状态、未清理的 timer 和已安装的 fake timers 可能跨文件保留;后续文件需要干净的环境时,必须显式重置这些状态。
模块 mock
由于模块在同一个 worker 的多个文件之间共享,当 isolate 为 false 时,模块 mock 的行为会有所不同:
- mock 可能不生效:如果之前的文件已经加载了某个引入被 mock 模块的模块,这个已缓存的模块会继续使用真实实现。
- mock 可能泄漏:mock 生效期间加载的模块,会在后续文件中继续使用 mock 实现。
具体哪个文件失败,取决于文件的执行顺序。
例如,下面两个测试文件都引入了 ./user-service,而它会调用 ./api 中的 fetchUser()。真实的 fetchUser() 返回 { name: 'Bob' },只有 user-service.test.ts 对它进行了 mock。为了让两个文件在任意执行顺序下都正确,mock 文件在引入被测代码之前重置模块缓存,并在文件结束后撤销 mock(高亮行):
profile.test.ts 无需任何修改:无论它在 user-service.test.ts 之前还是之后执行,拿到的都是真实的 ./api。
- 在
rs.hoisted()中调用rs.resetModules(),让模块缓存在静态 import 执行之前被清空。 - 在
afterAll中对该文件 mock 的每个模块调用rs.doUnmock()。 - 两次
rs.resetModules()都会清空共享的模块缓存,因此当前文件和同一 worker 中的下一个文件都会重新求值模块。没有使用这种写法的文件仍然共享模块。