Rstest
Use the vitest-auto-spy/rstest entry when your tests run on Rstest, the test runner built on the Rspack bundler. It has the same API as the Vitest entry and connects the spies to Rstest's mocks, so rstest.clearAllMocks() and Rstest's matchers see them.
// greeter.test.ts
import { describe, expect, it } from '@rstest/core';
import { type Spy, createSpyFromClass } from 'vitest-auto-spy/rstest';
class UserService {
getName(id: number): string {
return `user-${id}`;
}
async load(id: number): Promise<string> {
return `loaded-${id}`;
}
}
// the code under test: receives UserService through its constructor
class Greeter {
constructor(private readonly users: UserService) {}
greet(id: number): string {
return `Hello, ${this.users.getName(id)}!`;
}
async welcome(id: number): Promise<string> {
return `Welcome, ${await this.users.load(id)}`;
}
}
describe('Greeter', () => {
it('greets the user the service returns', async () => {
const users: Spy<UserService> = createSpyFromClass(UserService);
const greeter = new Greeter(users);
users.getName.calledWith(7).mockReturnValue('Ada'); // answers getName(7) only
users.load.resolveWith('Ada'); // no calledWith: answers every call
expect(greeter.greet(7)).toBe('Hello, Ada!');
expect(await greeter.welcome(1)).toBe('Welcome, Ada');
expect(users.getName).toHaveBeenCalledWith(7);
});
});npx rstest runNo setup file is required: importing from this entry registers everything. The example imports describe / it / expect from @rstest/core.
To use them without imports, set globals: true. Then rstest, Rstest's mock utility (like vi in Vitest), is a global too, with the short alias rs:
// rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
globals: true,
clearMocks: true, // clear every mock before each test; spies from createSpyFromClass included
});The native surface is Vitest-shaped
Rstest's own mock methods on a spy work as on Vitest:
spy.method.mock.calls[0]is a plain array of arguments;mockReturnValueand its relatives exist on the spy;mockClear()/mockReset()behave as on Vitest;gettersToSpyOn/settersToSpyOnwork. ThesecreateSpyFromClassoptions turn a class's getters or setters into spies.
Still prefer the library helpers (calledWith, resolveWith, nextWith, …): they read the same on every runner.
rstest.clearAllMocks() sweeps the library spies
rstest.clearAllMocks(), rstest.resetAllMocks() and the clearMocks: true / resetMocks: true config keys also clear spies built by createSpyFromClass. There is nothing extra to enable in this library: turn the config keys on in rstest.config.ts if you want them, as above. How this works is in In depth.
Beside this entry
These entries also work under Rstest, without Vitest installed:
vitest-auto-spy/console:useConsoleSpies()registers its hooks on Rstest'sbeforeEach/afterEachonce this entry is imported. Its types do not namevitesteither.vitest-auto-spy/nestjs: the Nest helpers build Rstest mocks. A Nest test importscreateNestUnitfrom/nestjsnext to this entry.
Other entries (the root vitest-auto-spy, /angular, /setup, /dom-stubs, /react, /vue, …) import vitest. Without Vitest installed, the run stops before any test with Cannot find package 'vitest' imported from …/node_modules/vitest-auto-spy/dist/<entry>.js. Import the factories from this entry instead. npx vitest-auto-spy doctor reports such an import as vitest-entry-without-vitest and names the entry to use.
The types of this entry do not reference vitest, so a project without Vitest type-checks cleanly, even with skipLibCheck: false. Spy<T> here has the same members as on Vitest, except Vitest's mockThrow; failWith() does the same on every runner.
What is not here yet
/setup(setupAutoSpy(), the fake-timer helpers, stray-rejection and stray-timer tracking) works only with Vitest's hooks. Rstest has no replacement for it yet.
Which runtime
Rstest is still 0.x. Vitest remains the default. Use this entry when your tests already run on Rstest, typically in an Rspack project that reuses its bundler config for tests.
In depth
- The library builds method spies itself, not with
rstest.fn(). To make Rstest's clear and reset reach them, the entry registers one hidden Rstest mock that passes the call on. - Accessor spies (
gettersToSpyOn/settersToSpyOn) redefine the property;rstest.spyOnis not used. trackNodeMocks()from thenode:testentry has no Rstest version and needs none: Rstest drops its mocks between files, like Vitest and Bun.