NestJS Vitest
Use this workflow to set up, migrate, or repair NestJS tests with Vitest.
Preflight checks (required)
- Confirm Nest backend root by checking all required files exist:
package.jsontsconfig.jsonsrc/main.tssrc/app.module.ts
- Detect package manager from lockfile and keep command style consistent:
package-lock.json->npmpnpm-lock.yaml->pnpmyarn.lock->yarn
- Confirm supported runtime:
- Prefer Node.js 20+.
- Stop early if required files are missing and report exact missing path(s) before editing.
Install and baseline configuration
- Install required dev dependencies:
npm install --save-dev vitest @vitest/coverage-v8 vite-tsconfig-paths
- Ensure
@nestjs/testingandsupertestare available for Nest unit/e2e tests. - Create or update
vitest.config.ts:
import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [tsconfigPaths()],
test: {
globals: true,
environment: 'node',
include: ['src/**/*.spec.ts', 'test/**/*.e2e-spec.ts'],
exclude: ['dist', 'node_modules'],
setupFiles: ['test/vitest.setup.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
reportsDirectory: 'coverage',
},
},
})
- Create or update
test/vitest.setup.ts:
import { afterEach, vi } from 'vitest'
afterEach(() => {
vi.restoreAllMocks()
vi.clearAllMocks()
})
- Update
package.jsonscripts:
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:cov": "vitest run --coverage",
"test:e2e": "vitest run test/**/*.e2e-spec.ts"
}
}
- Keep
vite-tsconfig-pathswhen the project uses TS path aliases. If no aliases are present, the plugin is optional.
Migration from Jest
- Convert Jest APIs in tests and helpers:
jest.fn->vi.fnjest.spyOn->vi.spyOnjest.mock->vi.mockjest.clearAllMocks->vi.clearAllMocksjest.restoreAllMocks->vi.restoreAllMocksjest.useFakeTimers->vi.useFakeTimersjest.useRealTimers->vi.useRealTimersjest.setSystemTime->vi.setSystemTime
- Remove Jest-only configuration once conversion is complete:
jest.config.*ts-jesttransforms- scripts invoking
jest
- If Jest must remain temporarily (monorepo/shared tooling), document that as an intentional exception.
NestJS test patterns
- Unit tests for providers/services:
- Build a
TestingModuleviaTest.createTestingModule. - Mock dependencies with
useValueandvi.fn. - Assert behavior at the service boundary.
- Controller tests:
- Validate delegation and response shaping.
- Stub service methods with
vi.fninstead of real external calls.
- e2e tests:
- Create and initialize
INestApplicationwithawait app.init(). - Use
supertestagainstapp.getHttpServer(). - Always run
await app.close()inafterAll.
See concrete snippets in examples.md.
Common pitfalls
- Path alias imports fail:
- Add
vite-tsconfig-pathsand ensure aliases exist intsconfig.json.
- Add
- Tests hang after completion:
- Ensure
await app.close()runs and fake timers are restored.
- Ensure
- Module mocks do not apply:
vi.mockis hoisted. Use patterns in reference.md for factory and hoisted values.
- Decorator or reflection issues:
- Keep
experimentalDecoratorsandemitDecoratorMetadataconsistent with the app tsconfig.
- Keep
Verification gates (required)
- Run unit tests:
test - Run e2e tests:
test:e2e - Run coverage:
test:cov - Confirm
coverage/was generated. - Confirm Jest-only config/scripts were removed or intentionally retained with reason documented.
- Confirm at least one unit and one e2e spec pass with Vitest.
- If any gate fails, report exact failing command and stop before claiming success.
Additional resources
- Advanced config and migration notes: reference.md
- Nest-focused example tests: examples.md