Nest.js × Vitest の環境構築
はじめに
Nest.js で Vitest を用いてテストの環境構築をしたので、その経緯と手順をまとめます。
Vitest を採用した理由
- HMR のように、変更があったモジュールだけを再実行することができ、実行速度が速いため
- esbuild によって ESM, TS が標準サポートされているため
- チームメンバーが推奨してくれたため
- 自分自身が参画していたプロジェクトで Jest を使用していましたが、テストの実行速度が気になっていたため
Vitest を使う上で懸念に思っていたこと
Jest と同じような API を提供していくれているのかが気になっていました。
調べたところ、公式にも以下のようなことが書かれており、Jest との互換性があるとのことでした。
Given Jest's massive adoption, Vitest provides a compatible API that allows you to use it as a drop-in replacement in most projects.
(DeepL 翻訳)
Jestが大量に採用されていることから、Vitestは互換性のあるAPIを提供しており、ほとんどのプロジェクトでJestをドロップインで置き換えることができます。
また、API Reference も見てみたところ、Jest と同じような API を提供していることがわかりました。
describe, it, expect などの API が提供されています。
また、beforeEach, afterEach などの Setup, Teardown 関数も用意されています。
モック関数についても、vi
ヘルパーを使ってモック関数を作成することができます。
環境構築
前提
以下のバージョンで Nest.js プロジェクト作成されていること
※ちなみに筆者は以下のバージョンでNestプロジェクトを作成しました。
パッケージ | バージョン |
---|---|
Node.js | 20.9.0 |
npm | 10.1.0 |
Nest.js | 10.2.9 |
手順
1. Jest のアンインストールと設定ファイル・記述の削除
- import type { Config } from 'jest'
-
- const config: Config = {
- moduleFileExtensions: ['js', 'json', 'ts'],
- rootDir: 'src',
- testRegex: '.*\\.spec\\.ts$',
- transform: {
- '^.+\\.(t|j)s$': 'ts-jest',
- },
- collectCoverageFrom: ['**/*.(t|j)s'],
- coverageDirectory: '../coverage',
- testEnvironment: 'node',
- }
-
- export default config
- {
- "moduleFileExtensions": ["js", "json", "ts"],
- "rootDir": ".",
- "testEnvironment": "node",
- "testRegex": ".e2e-spec.ts$",
- "transform": {
- "^.+\\.(t|j)s$": "ts-jest"
- }
- }
$ npm un -D jest @types/jest ts-jest
2. Vitest のインストールと設定ファイルの作成・記述
基本的に Nest 公式の Vitest セクションの手順に従います。
$ npm i --save-dev vitest unplugin-swc @swc/core @vitest/coverage-v8
+ import swc from 'unplugin-swc'
+ import { defineConfig } from 'vitest/config'
+
+ export default defineConfig({
+ test: {
+ globals: true,
+ root: './',
+ },
+ plugins: [
+ swc.vite({
+ module: { type: 'es6' },
+ }),
+ ],
+ })
+ import swc from 'unplugin-swc'
+ import { defineConfig } from 'vitest/config'
+
+ export default defineConfig({
+ test: {
+ include: ['**/*.e2e-spec.ts'],
+ globals: true,
+ root: './',
+ },
+ plugins: [swc.vite()],
+ })
ESM の記述になるため、.mts
という拡張子にしています。
または、package.json の type フィールドに module
を追加することで、.ts
という拡張子でも記述できます。
+ {
+ "type": "module",
+ }
3. テストスクリプトの設定
"scripts": {
- "test": "jest",
- "test:watch": "jest --watch",
- "test:cov": "jest --coverage",
- "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
- "test:e2e": "jest --config ./test/jest-e2e.json"
+ "test": "vitest run",
+ "test:watch": "vitest",
+ "test:cov": "vitest run --coverage",
+ "test:debug": "vitest --inspect-brk --inspect --logHeapUsage --poolOptions.threads.singleThread",
+ "test:e2e": "vitest run --config ./vitest.config.e2e.mts"
},
4. ダミーのテストファイルにテストを記述
import { Test, type TestingModule } from '@nestjs/testing'
import { beforeEach, describe, expect, it } from 'vitest'
import { AuthController } from './auth.controller'
describe('AuthController', () => {
let controller: AuthController
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [AuthController],
}).compile()
controller = module.get<AuthController>(AuthController)
})
it('Controller が定義されていること', () => {
expect(controller).toBeDefined()
})
})
5. テストの実行
$ npm run test
おまけの設定
- VSCode 拡張機能のインストール
VSCode 上でテストの実行と、テストファイル内でテストの結果を表示できるようになります。
チームメンバーにもおすすめしておきましょう。
{
"recommendations": [
// ...
+ "zixuanchen.vitest-explorer"
]
}
- CI でのテストの実行
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: checkout
+ uses: actions/checkout@v4
+ - name: setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: './package.json'
+ - name: clean install
+ run: npm ci
+ - name: test
+ run: npm run test
+
+ test-e2e:
+ runs-on: ubuntu-latest
+ steps:
+ - name: checkout
+ uses: actions/checkout@v4
+ - name: setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: './package.json'
+ - name: clean install
+ run: npm ci
+ - name: test
+ run: npm run test:e2e
ベンチマーク
Jest と Vitest の実行速度を比較してみました。
1つのテストだけで約2.9倍、約1秒の速度差がありました。
驚きです。
Jest
1.386s
Vitest
477ms
おわりに
Vitest を採用してみて、テストの実行速度が速くなることを実感しました。
Jest との互換性もあるため、移行もスムーズにできると思うので、ぜひ試してみてください。
Discussion