Migrating from Vitest
If you are using the Rstack toolchain (Rsbuild / Rslib / Rspack, etc.), migrating to Rstest gives you a more consistent development experience.
Using Agent Skills
If you are using a Coding Agent that supports Skills, install the migrate-to-rstest skill to help with the upgrade process from Vitest to Rstest.
After installation, let the Coding Agent guide you through the upgrade.
Installation and setup
First, you need to install Rstest as a development dependency.
Next, update the test script in your package.json to use rstest instead of vitest. For example:
rstest does not have a --run flag. Running rstest already executes tests once and exits. If you want watch mode, use --watch:
CLI option mappings
Some Vitest CLI flags map directly to Rstest, while others change shape. Use this table for the common option differences you are likely to hit during migration:
Configuration migration
Update your Vitest config file (e.g., vite.config.ts or vitest.config.ts) to a rstest.config.ts file:
Helper imports
Vitest's config-file helpers map to equivalents in @rstest/core:
Vitest configuration mappings
When migrating config, keep two changes in mind:
- Remove the
testfield and move its nested properties to the top level. - Rename keys when required (for example,
test.environment→testEnvironment).
Walk through every option under test and match it against the table below — move it to the top level, rename it, or drop it. Fields not listed here may not map 1:1; verify against the Rstest config reference before dropping them silently.
Build configuration
Rstest uses Rsbuild as the default test build tool instead of Vite. You can view all available build configuration options in Build Configurations.
In most projects, these are the key build-side changes:
- Use
source.defineinstead ofdefine. - Use
output.externalsinstead ofssr.external. - Use Rsbuild plugins instead of Vite plugins.
If you are using Rslib or Rsbuild, you can directly use the corresponding adapter:
- For Rslib projects (with
rslib.config.*), use@rstest/adapter-rslibwithextends: withRslibConfig()(see Rslib integration reference). - For Rsbuild projects (with
rsbuild.config.*), use@rstest/adapter-rsbuildwithextends: withRsbuildConfig()(see Rsbuild integration reference).
Update test API
Test API
Your existing Vitest test files should work with minimal changes since Rstest provides Vitest-compatible APIs. Update your imports from vitest to @rstest/core, and replace vi / vitest utilities with their rs / rstest equivalents:
For the full utility API list, see Rstest APIs.
Global APIs
When globals: true is enabled, vi and vitest are available as globals in Vitest. In Rstest, use this mapping order:
vi.<api>→rs.<api>vitest.<api>→rstest.<api>
rs and rstest are equivalent global aliases, but keeping this one-to-one mapping is easier to read during migration.
If your tests import APIs from @rstest/core, prefer rs.<api> in import style and avoid mixing import style and global style in the same file.
Setup adapters
Some setup adapters are Vitest-specific. For example, @testing-library/jest-dom/vitest is designed for Vitest; in Rstest, register the matchers directly via expect.extend.
Path resolution
Depending on your transform/runtime mode, new URL(..., import.meta.url) may fail in setup or helper files.
If you see path errors such as Cannot find module './' or Cannot find module '..', prefer Node-style path resolution with __dirname:
Auto-mocking modules
In Vitest, calling vi.mock() with just the module path first attempts to load a manual mock from the corresponding __mocks__ directory. If no manual mock is found, it automatically mocks the module, replacing all its exports with empty mock functions.
Rstest handles this differently. Calling rs.mock() with only the module path will only look for a mock in the __mocks__ directory and will throw an error if one isn't found. Auto-mocking requires explicitly passing the { mock: true } option.
Mock async modules
When you need to mock a module's return value, Rstest does not support returning an async function.
As an alternative, Rstest provides synchronous importActual capability, allowing you to import the unmocked module implementation through static import statements:
Because mock factories are hoisted, avoid relying on values initialized later in the same module. If needed, move shared values to a hoisted initializer (for example rs.hoisted(...)) to avoid initialization-order errors.
Snapshots
Vitest and Rstest use the same snapshot key format and body serializer. Existing __snapshots__/*.snap files from a Vitest suite are read verbatim by Rstest, and tests that passed under Vitest continue to pass under Rstest without re-recording. Only the file header line differs:
Running rstest -u normalizes this header to the Rstest form; the snapshot bodies stay byte-identical.