0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vitestを使う

Last updated at Posted at 2025-08-03

Vitest は JavaScript/TypeScript のテストフレームワークである。

Vite をインストールしていないプロジェクトでも使える。

インストールする

$ npm i -D vitest

package.jsonに以下をマージする。

package.json
{
  "scripts": {
+   "test": "vitest"
  }
}

以下で*.test.tsのテストコードを実行することができる。

$ npm run test

以下で特定のファイルのテストコードを実行することができる。

$ npx vitest src/path/to/code.test.ts

基本

import {
  afterAll,
  beforeAll,
  beforeEach,
  describe,
  expect,
  test,
} from "vitest";

describe("基本", () => {
  beforeAll(() => {
    console.log("すべてのテストが始まる前に呼ばれるコード");
  });

  beforeEach(() => {
    console.log("各テストの前に毎回呼ばれるコード");
  });

  describe("値の確認系", () => {
    test("toBe()はプリミティブな値を比較できる", () => {
      expect(1 + 1).toBe(2);
    });

    test("toBe()はオブジェクトの参照が同じか確認できる", () => {
      const obj = { key: "value" };
      expect(obj).toBe(obj);
    });

    test("notを使うと否定できる", () => {
      const obj1 = { key: "value" };
      const obj2 = { key: "value" };
      expect(obj1).not.toBe(obj2);
    });

    test("toEqual()はオブジェクトの値が等しいことを確認できる", () => {
      expect(["a", "b"]).toEqual(["a", "b"]);
    });

    test("toHaveProperty()はプロパティを持っていることを確認できる", () => {
      expect({ key: "value" }).toHaveProperty("key");
    });

    test("toBeDefined()はnullishでないことを確認できる", () => {
      expect({}).toBeDefined();
    });
  });

  afterAll(() => {
    console.log("すべてのテストが終わったときに呼ばれるコード");
  });
});

例外の捕捉系

import { describe, expect, test } from "vitest";

describe("例外の捕捉系", () => {
  test("同期的に特定の例外が発生することを確認できる", async () => {
    function throwingErrorFunction() {
      throw new Error("Something happened");
    }
    expect(throwingErrorFunction).toThrow(new Error("Something happened"));
  });

  test("引数を渡しつつ同期的に特定の例外が発生することを確認できる", async () => {
    function throwingErrorFunction(args: string) {
      throw new Error("Something happened");
    }
    expect(() => throwingErrorFunction("args")).toThrow(
      new Error("Something happened")
    );
  });

  test("非同期的に特定の例外が発生することを確認できる", async () => {
    async function throwingErrorAsyncFunction(): Promise<void> {
      return new Promise((resolve) => {
        throw new Error("Something happened");
      });
    }
    expect(throwingErrorAsyncFunction).rejects.toThrow(
      new Error("Something happened")
    );
  });
});

時間がかかる系

import { describe, expect, test } from "vitest";

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

describe("時間がかかる系", () => {
  test(
    "テストに5秒以上かかるとタイムアウトでNGになるが{ timeout: Infinity }を指定してやると5秒以上のテストも実施できる",
    { timeout: Infinity },
    async () => {
      const then = performance.now();
      await sleep(10000);
      const now = performance.now();
      expect(now - then).greaterThanOrEqual(9900);
    }
  );
});

モック系

import { describe, expect, test, vitest } from "vitest";

class NotToBeTestedClass {
  sayHello() {
    return "Hello";
  }
}

class ToBeTestedClass {
  constructor(public readonly notToBeTestedClass: NotToBeTestedClass) {}
  sayHello() {
    return this.notToBeTestedClass.sayHello();
  }
}

describe("モック系", () => {
  test("ビルトインメソッドをモックできる", () => {
    const spy = vitest.spyOn(Math, "random").mockImplementation(() => 0.1);
    const value = Math.random();
    expect(spy).toBeCalled();
    expect(value).toBe(0.1);
  });

  test("テスト対象じゃないクラスのメソッドをモック化できる", () => {
    const notToBeTestedClass = new NotToBeTestedClass();
    const toBeTestedClass = new ToBeTestedClass(notToBeTestedClass);
    const spy = vitest
      .spyOn(toBeTestedClass, "sayHello")
      .mockImplementation(() => "Hi");
    const value = toBeTestedClass.sayHello();
    expect(spy).toBeCalled();
    expect(value).toBe("Hi");
  });
});

テスト用の環境変数を設定する

$ npm i @dotenvx/dotenvx
vitest.config.ts
/// <reference types="vitest" />
import { defineConfig } from "vite";

+ import dotenvx from "@dotenvx/dotenvx";

export default defineConfig({
+ test: {
+   env: dotenvx.config({ path: ".env.test" }).parsed,
+ },
});
.env.test
PORT=8080

上記の環境変数の例だとテストコード側ではprocess.env.PORTで参照することができる。

テストファイルを 1 つずつ実行させる

Vitest はデフォルトでテストファイルを並列して実行する。 このためリソースの奪い合いでエラーが起きたりする。

fileParallelismfalseにすることでテストファイルを 1 つずつ実行させることができる。

vitest.config.ts
/// <reference types="vitest" />
import { defineConfig } from "vite";

export default defineConfig({
  test: {
+   fileParallelism: false,
  },
});
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?