Skip to content
Vitest 1
Main Navigation ガイドAPI設定高度な
1.6.1
0.34.6

日本語

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
한국어
Italiano
Polski
Türkçe
čeština
magyar

日本語

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
한국어
Italiano
Polski
Türkçe
čeština
magyar

外観

Sidebar Navigation

ガイド

Vitest の必要性

はじめに

特徴

ワークスペース

コマンドラインインターフェース

テストのフィルタリング

レポーター

カバレッジ

スナップショット

モック

型テスト

Vitest UI

ブラウザモード

ソース内テスト

テストコンテキスト

テスト環境

マッチャー拡張

IDE 連携機能

デバッグ

他のテストランナーとの比較

マイグレーションガイド

よくあるエラー

パフォーマンスの改善

API

テスト API リファレンス

モック関数

Vi

expect

expectTypeOf

assert

assertType

設定

Vitestの設定ファイル管理

Vitestの設定

このページの内容

expect ​

以下の型シグネチャで使用される型は次の通りです。

ts
type Awaitable<T> = T | PromiseLike<T>;

expect はアサーションを作成するために使用されます。このコンテキストにおいて、アサーション とは、ステートメントの正しさを検証するために呼び出すことができる関数のことです。Vitest はデフォルトで chai のアサーションを提供し、chai を基盤として構築された Jest 互換のアサーションも提供します。

例えば、以下のコードは input の値が 2 と等しいことを検証します。等しくない場合、アサーションはエラーをスローし、テストが失敗します。

ts
import { expect } from 'vitest';

const input = Math.sqrt(4);

expect(input).to.equal(2); // chai API
expect(input).toBe(2); // jest API

厳密に言えば、この例では test 関数を使用していないため、コンソールには Vitest の出力ではなく Node.js のエラーが表示されます。test についてより詳しく知りたい場合は、テスト API リファレンス を参照してください。

また、expect は後述するマッチャー関数などに静的にアクセスすることもできます。

WARNING

expect は、式に型エラーがない場合、型のテストには影響を与えません。Vitest を 型チェッカー として使用したい場合は、expectTypeOf または assertType を使用してください。

soft ​

  • 型: ExpectStatic & (actual: any) => Assertions

expect.soft は expect と同様に機能しますが、アサーションが失敗した場合にテストの実行を終了する代わりに、実行を継続し、失敗をテストの失敗として記録します。テスト中に発生したすべてのエラーは、テストが完了するまで表示されます。

ts
import { expect, test } from 'vitest';

test('expect.soft test', () => {
  expect.soft(1 + 1).toBe(3); // テストを失敗として記録し、処理を継続します
  expect.soft(1 + 2).toBe(4); // テストを失敗として記録し、処理を継続します
});
// テストの最後に、上記のエラーが表示されます。

expect と組み合わせて使用することも可能です。expect のアサーションが失敗した場合、テストは終了し、全てのエラーが表示されます。

ts
import { expect, test } from 'vitest';

test('expect.soft test', () => {
  expect.soft(1 + 1).toBe(3); // テストを失敗として記録し、処理を継続します
  expect(1 + 2).toBe(4); // 失敗してテストを終了し、以前のエラーがすべて出力されます
  expect.soft(1 + 3).toBe(5); // 実行されません
});

WARNING

expect.soft は、test 関数内でのみ使用できます。

not ​

not を使用すると、アサーションの結果が反転します。例えば、以下のコードは input の値が 2 と等しくないことを検証します。等しい場合、アサーションはエラーをスローし、テストが失敗します。

ts
import { expect, test } from 'vitest';

const input = Math.sqrt(16);

expect(input).not.to.equal(2); // chai API
expect(input).not.toBe(2); // jest API

toBe ​

  • 型: (value: any) => Awaitable<void>

toBe は、プリミティブが厳密に等しいか、オブジェクトが同じ参照を共有しているかを検証するために使用できます。これは expect(Object.is(3, 3)).toBe(true) を呼び出すのと同じです。オブジェクトが同じではないものの、その構造が同一であるかどうかを確認したい場合は、toEqual を使用してください。

例えば、以下のコードは、トレーダーが 13 個のリンゴを所有しているかどうかを確認します。

ts
import { expect, test } from 'vitest';

const stock = {
  type: 'apples',
  count: 13,
};

test('stock has 13 apples', () => {
  expect(stock.type).toBe('apples');
  expect(stock.count).toBe(13);
});

test('stocks are the same', () => {
  const refStock = stock; // same reference(同じ参照)

  expect(stock).toBe(refStock);
});

浮動小数点数で toBe を使用しないようにしてください。JavaScript はそれらを丸めるため、0.1 + 0.2 は厳密には 0.3 ではありません。浮動小数点数を確実に検証するには、toBeCloseTo アサーションを使用してください。

toBeCloseTo ​

  • 型: (value: number, numDigits?: number) => Awaitable<void>

toBeCloseTo を使用して、浮動小数点数を比較します。オプションの numDigits 引数は、小数点 以下 をチェックする桁数を制限します。例えば:

ts
import { expect, test } from 'vitest';

test.fails('decimals are not equal in javascript', () => {
  expect(0.2 + 0.1).toBe(0.3); // 0.2 + 0.1 is 0.30000000000000004
});

test('decimals are rounded to 5 after the point', () => {
  // 0.2 + 0.1 is 0.30000 | "000000000004" removed
  expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
  // nothing from 0.30000000000000004 is removed
  expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50);
});

toBeDefined ​

  • 型: () => Awaitable<void>

toBeDefined は、値が undefined と等しくないことを検証します。関数の 戻り値 が何らかの値を持つかどうかを確認する場合に便利です。

ts
import { expect, test } from 'vitest';

function getApples() {
  return 3;
}

test('function returned something', () => {
  expect(getApples()).toBeDefined();
});

toBeUndefined ​

  • 型: () => Awaitable<void>

toBeDefined の反対で、toBeUndefined は、値が undefined と等しい ことを検証します。関数が何も 返していない かどうかを確認する場合に便利です。

ts
import { expect, test } from 'vitest';

function getApplesFromStock(stock: string) {
  if (stock === 'Bill') return 13;
}

test("mary doesn't have a stock", () => {
  expect(getApplesFromStock('Mary')).toBeUndefined();
});

toBeTruthy ​

  • 型: () => Awaitable<void>

toBeTruthy は、値がブール値に変換されたときに true であることを検証します。値の具体的な内容を気にせず、true に変換できるかどうかを知りたい場合に便利です。

例えば、このコードでは、stocks.getInfo の戻り値を気にしません。それは複雑なオブジェクト、文字列、またはその他の何かかもしれません。コードはそれでも動作します。

ts
import { Stocks } from './stocks.js';

const stocks = new Stocks();
stocks.sync('Bill');
if (stocks.getInfo('Bill')) stocks.sell('apples', 'Bill');

したがって、stocks.getInfo が truthy であることをテストしたい場合は、次のように記述できます。

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test('if we know Bill stock, sell apples to him', () => {
  stocks.sync('Bill');
  expect(stocks.getInfo('Bill')).toBeTruthy();
});

JavaScript のすべての値は truthy です。ただし、false, null, undefined, NaN, 0, -0, 0n, ""、および document.all は除きます。

toBeFalsy ​

  • 型: () => Awaitable<void>

toBeFalsy は、値がブール値に変換されたときに false であることを検証します。値の具体的な内容を気にせず、false に変換できるかどうかを知りたい場合に便利です。

例えば、このコードでは、stocks.stockFailed の戻り値を気にしません。それは任意の falsy 値を返すかもしれませんが、コードはそれでも動作します。

ts
import { Stocks } from './stocks.js';

const stocks = new Stocks();
stocks.sync('Bill');
if (!stocks.stockFailed('Bill')) stocks.sell('apples', 'Bill');

したがって、stocks.stockFailed が falsy であることをテストしたい場合は、次のように記述できます。

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test("if Bill stock hasn't failed, sell apples to him", () => {
  stocks.syncStocks('Bill');
  expect(stocks.stockFailed('Bill')).toBeFalsy();
});

JavaScript のすべての値は truthy です。ただし、false, null, undefined, NaN, 0, -0, 0n, ""、および document.all は除きます。

toBeNull ​

  • 型: () => Awaitable<void>

toBeNull は、値が null であるかどうかを検証します。.toBe(null) のエイリアスです。

ts
import { expect, test } from 'vitest';

function apples() {
  return null;
}

test("we don't have apples", () => {
  expect(apples()).toBeNull();
});

toBeNaN ​

  • 型: () => Awaitable<void>

toBeNaN は、値が NaN であるかどうかを検証します。.toBe(NaN) のエイリアスです。

ts
import { expect, test } from 'vitest';

let i = 0;

function getApplesCount() {
  i++;
  return i > 1 ? Number.NaN : i;
}

test('getApplesCount has some unusual side effects...', () => {
  expect(getApplesCount()).not.toBeNaN();
  expect(getApplesCount()).toBeNaN();
});

toBeTypeOf ​

  • 型: (c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>

toBeTypeOf は、実際の値が指定された型の型であるかどうかを検証します。

ts
import { expect, test } from 'vitest';

const actual = 'stock';

test('stock is type of string', () => {
  expect(actual).toBeTypeOf('string');
});

toBeInstanceOf ​

  • 型: (c: any) => Awaitable<void>

toBeInstanceOf は、実際の値が指定されたクラスのインスタンスであるかどうかを検証します。

ts
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';

const stocks = new Stocks();

test('stocks are instance of Stocks', () => {
  expect(stocks).toBeInstanceOf(Stocks);
});

toBeGreaterThan ​

  • 型: (n: number | bigint) => Awaitable<void>

toBeGreaterThan は、実際の値が指定された値より大きいかどうかを検証します。等しい値はテストに失敗します。

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have more then 10 apples', () => {
  expect(getApples()).toBeGreaterThan(10);
});

toBeGreaterThanOrEqual ​

  • 型: (n: number | bigint) => Awaitable<void>

toBeGreaterThanOrEqual は、実際の値が指定された値以上であるかどうかを検証します。

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have 11 apples or more', () => {
  expect(getApples()).toBeGreaterThanOrEqual(11);
});

toBeLessThan ​

  • 型: (n: number | bigint) => Awaitable<void>

toBeLessThan は、実際の値が指定された値より小さいかどうかを検証します。等しい値はテストに失敗します。

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have less then 20 apples', () => {
  expect(getApples()).toBeLessThan(20);
});

toBeLessThanOrEqual ​

  • 型: (n: number | bigint) => Awaitable<void>

toBeLessThanOrEqual は、実際の値が指定された値以下であるかどうかを検証します。

ts
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';

test('have 11 apples or less', () => {
  expect(getApples()).toBeLessThanOrEqual(11);
});

toEqual ​

  • 型: (received: any) => Awaitable<void>

toEqual は、実際の値が指定された値と等しいか、オブジェクトである場合は同じ構造を持っているかどうかを検証します(再帰的に比較します)。toEqual と toBe の違いは、次の例で確認できます。

ts
import { expect, test } from 'vitest';

const stockBill = {
  type: 'apples',
  count: 13,
};

const stockMary = {
  type: 'apples',
  count: 13,
};

test('stocks have the same properties', () => {
  expect(stockBill).toEqual(stockMary);
});

test('stocks are not the same', () => {
  expect(stockBill).not.toBe(stockMary);
});

WARNING

Errorオブジェクトに対して、深層的な等価性の比較は行われません。Error のmessageプロパティのみが等価性の比較対象となります。message以外のプロパティをチェックするために等価性をカスタマイズするには、expect.addEqualityTestersを使用してください。何かが例外をスローしたかどうかをテストするには、toThrowErrorアサーションを使用してください。

toStrictEqual ​

  • 型: (received: any) => Awaitable<void>

toStrictEqual は、実際の値が指定された値と等しいか、オブジェクトである場合は同じ構造を持っているかどうか(再帰的に比較します)、および同じ型であるかどうかを検証します。

.toEqual との違い:

  • undefined プロパティを持つキーがチェックされます。例えば、.toStrictEqual を使用すると、{a: undefined, b: 2} は {b: 2} と一致しません。
  • 配列の疎性がチェックされます。例えば、.toStrictEqual を使用すると、[, 1] は [undefined, 1] と一致しません。
  • オブジェクトの型が等しいかどうかがチェックされます。例えば、フィールド a と b を持つクラス インスタンスは、フィールド a と b を持つリテラル オブジェクトと等しくありません。
ts
import { expect, test } from 'vitest';

class Stock {
  constructor(type) {
    this.type = type;
  }
}

test('structurally the same, but semantically different', () => {
  expect(new Stock('apples')).toEqual({ type: 'apples' });
  expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' });
});

toContain ​

  • 型: (received: string) => Awaitable<void>

toContainは、実際の値が配列に含まれているかどうかをアサートします。toContainは、ある文字列が別の文字列の部分文字列であるかどうかをチェックすることもできます。Vitest 1.0 以降では、ブラウザのような環境でテストを実行している場合、このアサーションは、クラスがclassListに含まれているかどうか、または要素が別の要素内にあるかどうかをチェックすることもできます。

ts
import { expect, test } from 'vitest';
import { getAllFruits } from './stocks.js';

test('the fruit list contains orange', () => {
  expect(getAllFruits()).toContain('orange');

  const element = document.querySelector('#el');
  // element has a class
  expect(element.classList).toContain('flex');
  // element is inside another one
  expect(document.querySelector('#wrapper')).toContain(element);
});

toContainEqual ​

  • 型: (received: any) => Awaitable<void>

toContainEqual は、特定の構造と値を持つアイテムが配列に含まれているかどうかを検証します。 各要素に対して toEqual のように機能します。

ts
import { expect, test } from 'vitest';
import { getFruitStock } from './stocks.js';

test('apple available', () => {
  expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 });
});

toHaveLength ​

  • 型: (received: number) => Awaitable<void>

toHaveLength は、オブジェクトに .length プロパティがあり、それが指定された数値に設定されているかどうかを検証します。

ts
import { expect, test } from 'vitest';

test('toHaveLength', () => {
  expect('abc').toHaveLength(3);
  expect([1, 2, 3]).toHaveLength(3);

  expect('').not.toHaveLength(3); // doesn't have .length of 3
  expect({ length: 3 }).toHaveLength(3);
});

toHaveProperty ​

  • Type: (key: any, received?: any) => Awaitable<void>

toHaveProperty は、オブジェクトが指定された key のプロパティを持っているかどうかを検証します。

オプションの received 引数(deep equality とも呼ばれます)を toEqual マッチャーのように指定することで、プロパティの値が一致するかどうかを検証できます。

ts
import { expect, test } from 'vitest';

const invoice = {
  isActive: true,
  'P.O': '12345',
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

test('John Doe Invoice', () => {
  expect(invoice).toHaveProperty('isActive'); // キーの存在をアサート
  expect(invoice).toHaveProperty('total_amount', 5000); // キーが存在し、値が等しいことをアサート

  expect(invoice).not.toHaveProperty('account'); // このキーが存在しないことをアサート

  // ドット記法を使用した深い参照
  expect(invoice).toHaveProperty('customer.first_name');
  expect(invoice).toHaveProperty('customer.last_name', 'Doe');
  expect(invoice).not.toHaveProperty('customer.location', 'India');

  // キーを含む配列を使用した深い参照
  expect(invoice).toHaveProperty('items[0].type', 'apples');
  expect(invoice).toHaveProperty('items.0.type', 'apples'); // ドット記法も使用可能

  // キーパスを含む配列を使用した深い参照
  expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples');
  expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // 文字列記法も使用可能

  // キーが深い参照として解釈されないように、キーを配列で囲む
  expect(invoice).toHaveProperty(['P.O'], '12345');
});

toMatch ​

  • Type: (received: string | regexp) => Awaitable<void>

toMatch は、文字列が正規表現または文字列に一致するかどうかをアサートします。

ts
import { expect, test } from 'vitest';

test('top fruits', () => {
  expect('top fruits include apple, orange and grape').toMatch(/apple/);
  expect('applefruits').toMatch('fruit'); // toMatch は文字列も受け付けます
});

toMatchObject ​

  • Type: (received: object | array) => Awaitable<void>

toMatchObject は、オブジェクトが別のオブジェクトのプロパティのサブセットと一致するかどうかをアサートします。

オブジェクトの配列を渡すことも可能です。これは、受け取った配列に余分な要素が含まれることを許容する arrayContaining とは異なり、2 つの配列の要素数が一致するかどうかを検証する際に役立ちます。

ts
import { expect, test } from 'vitest';

const johnInvoice = {
  isActive: true,
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

const johnDetails = {
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
};

test('invoice has john personal details', () => {
  expect(johnInvoice).toMatchObject(johnDetails);
});

test('the number of elements must match exactly', () => {
  // オブジェクトの配列が一致することをアサート
  expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([
    { foo: 'bar' },
    { baz: 1 },
  ]);
});

toThrowError ​

  • Type: (received: any) => Awaitable<void>

  • Alias: toThrow

toThrowError は、関数が呼び出されたときにエラーをスローするかどうかをアサートします。

特定のエラーがスローされることを検証するために、オプションの引数を指定できます。

  • 正規表現: エラーメッセージがパターンに一致するかどうか
  • 文字列: エラーメッセージにサブストリングが含まれているかどうか

TIP

テスト対象のコードを関数内でラップする必要があります。そうしないと、エラーがキャッチされず、テストは失敗します。

たとえば、getFruitStock('pineapples') がエラーをスローすることをテストする場合、次のように記述できます。

ts
import { expect, test } from 'vitest';

function getFruitStock(type: string) {
  if (type === 'pineapples') throw new Error('Pineapples are not in stock');

  // 他の処理
}

test('throws on pineapples', () => {
  // エラーメッセージに "stock" が含まれていることをテストします。これらは同じ意味です。
  expect(() => getFruitStock('pineapples')).toThrowError(/stock/);
  expect(() => getFruitStock('pineapples')).toThrowError('stock');

  // 正確なエラーメッセージをテストします
  expect(() => getFruitStock('pineapples')).toThrowError(
    /^Pineapples are not in stock$/
  );
});

TIP

非同期関数をテストするには、rejects と組み合わせて使用してください。

js
function getAsyncFruitStock() {
  return Promise.reject(new Error('empty'));
}

test('throws on pineapples', async () => {
  await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty');
});

toMatchSnapshot ​

  • Type: <T>(shape?: Partial<T> | string, message?: string) => void

これにより、値が最新のスナップショットと一致することを確認します。

テスト名に追加されるオプションの hint 文字列引数を指定できます。Vitest はスナップショット名の末尾に番号を付与しますが、短い説明的なヒントの方が、単一の it または test ブロック内の複数のスナップショットを区別するのに役立つ場合があります。Vitest は、対応する .snap ファイル内のスナップショットを名前でソートします。

TIP

スナップショットが一致せずテストが失敗した場合、その不一致が予期されたものであれば、u キーを押してスナップショットを一時的に更新できます。 または、-u または --update CLI オプションを渡して、Vitest が常にテストを更新するようにすることもできます。

ts
import { expect, test } from 'vitest';

test('matches snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchSnapshot();
});

オブジェクトの形状のみをテストしていて、100% の互換性が必要ない場合は、オブジェクトの形状を指定することもできます。

ts
import { expect, test } from 'vitest';

test('matches snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchSnapshot({ foo: expect.any(Set) });
});

toMatchInlineSnapshot ​

  • Type: <T>(shape?: Partial<T> | string, snapshot?: string, message?: string) => void

これにより、値が最新のインラインスナップショットと一致することを確認します。

Vitest は、inlineSnapshot 文字列引数を、外部の .snap ファイルではなく、テストファイル内のマッチャーに追加および更新します。

ts
import { expect, test } from 'vitest';

test('matches inline snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  // Vitest はスナップショットの更新時に次のコンテンツを更新します
  expect(data).toMatchInlineSnapshot(`
    {
      "foo": Set {
        "bar",
        "snapshot",
      },
    }
  `);
});

オブジェクトの形状のみをテストしていて、100% の互換性が必要ない場合は、オブジェクトの形状を指定することもできます。

ts
import { expect, test } from 'vitest';

test('matches snapshot', () => {
  const data = { foo: new Set(['bar', 'snapshot']) };
  expect(data).toMatchInlineSnapshot(
    { foo: expect.any(Set) },
    `
    {
      "foo": Any<Set>,
    }
  `
  );
});

toMatchFileSnapshot 0.30.0+ ​

  • Type: <T>(filepath: string, message?: string) => Promise<void>

スナップショットを、明示的に指定されたファイルの内容と比較または更新します(.snap ファイルの代替)。

ts
import { expect, it } from 'vitest';

it('render basic', async () => {
  const result = renderHTML(h('div', { class: 'foo' }));
  await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});

ファイルシステムの操作は非同期であるため、toMatchFileSnapshot() で await を使用する必要があることに注意してください。

toThrowErrorMatchingSnapshot ​

  • Type: (message?: string) => void

toMatchSnapshot と同じですが、toThrowError と同じ値を予期します。

toThrowErrorMatchingInlineSnapshot ​

  • Type: (snapshot?: string, message?: string) => void

toMatchInlineSnapshot と同じですが、toThrowError と同じ値を予期します。

toHaveBeenCalled ​

  • Type: () => Awaitable<void>

このアサーションは、関数が呼び出されたかどうかをテストするのに役立ちます。 expect にはスパイ関数を渡す必要があります。

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function', () => {
  const buySpy = vi.spyOn(market, 'buy');

  expect(buySpy).not.toHaveBeenCalled();

  market.buy('apples', 10);

  expect(buySpy).toHaveBeenCalled();
});

toHaveBeenCalledTimes ​

  • Type: (amount: number) => Awaitable<void>

このアサーションは、関数が特定の回数呼び出されたかどうかを検証します。expect にはスパイ関数を渡す必要があります。

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function called two times', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenCalledTimes(2);
});

toHaveBeenCalledWith ​

  • Type: (...args: any[]) => Awaitable<void>

このアサーションは、関数が特定の引数で少なくとも 1 回呼び出されたかどうかを検証します。expect にはスパイ関数を渡す必要があります。

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenCalledWith('apples', 10);
  expect(buySpy).toHaveBeenCalledWith('apples', 20);
});

toHaveBeenLastCalledWith ​

  • Type: (...args: any[]) => Awaitable<void>

このアサーションは、関数が最後の呼び出しで特定の引数で呼び出されたかどうかを検証します。expect にはスパイ関数を渡す必要があります。

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('spy function', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).not.toHaveBeenLastCalledWith('apples', 10);
  expect(buySpy).toHaveBeenLastCalledWith('apples', 20);
});

toHaveBeenNthCalledWith ​

  • Type: (time: number, ...args: any[]) => Awaitable<void>

このアサーションは、関数が特定の呼び出し回数で、特定の引数で呼び出されたかどうかを検証します。カウントは 1 から始まります。したがって、2 回目の呼び出しを検証するには、.toHaveBeenNthCalledWith(2, ...) と記述します。

expect にはスパイ関数を渡す必要があります。

ts
import { expect, test, vi } from 'vitest';

const market = {
  buy(subject: string, amount: number) {
    // ...
  },
};

test('first call of spy function called with right params', () => {
  const buySpy = vi.spyOn(market, 'buy');

  market.buy('apples', 10);
  market.buy('apples', 20);

  expect(buySpy).toHaveBeenNthCalledWith(1, 'apples', 10);
});

toHaveReturned ​

  • Type: () => Awaitable<void>

このアサーションは、関数が少なくとも 1 回正常に値を返したかどうか (エラーをスローしなかったかどうか) を検証します。expect にはスパイ関数を渡す必要があります。

ts
import { expect, test, vi } from 'vitest';

function getApplesPrice(amount: number) {
  const PRICE = 10;
  return amount * PRICE;
}

test('spy function returned a value', () => {
  const getPriceSpy = vi.fn(getApplesPrice);

  const price = getPriceSpy(10);

  expect(price).toBe(100);
  expect(getPriceSpy).toHaveReturned();
});

toHaveReturnedTimes ​

  • Type: (amount: number) => Awaitable<void>

このアサーションは、関数が指定された回数だけ正常に値を返したかどうか (エラーをスローしなかったかどうか) を検証します。expect にはスパイ関数を渡す必要があります。

ts
import { expect, test, vi } from 'vitest';

test('spy function returns a value two times', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');
  sell('bananas');

  expect(sell).toHaveReturnedTimes(2);
});

toHaveReturnedWith ​

  • 型: (returnValue: any) => Awaitable<void>

このアサーションは、関数が少なくとも一度、特定の値を正常に返したかどうかを検証します。expect に渡されるのはスパイ関数である必要があります。

ts
import { expect, test, vi } from 'vitest';

test('スパイ関数が商品を返す', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');

  expect(sell).toHaveReturnedWith({ product: 'apples' });
});

toHaveLastReturnedWith ​

  • 型: (returnValue: any) => Awaitable<void>

このアサーションは、関数が最後に呼び出された際に、特定の値を正常に返したかどうかを検証します。expect に渡されるのはスパイ関数である必要があります。

ts
import { expect, test, vi } from 'vitest';

test('スパイ関数が最後の呼び出しで bananas を返す', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');
  sell('bananas');

  expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});

toHaveNthReturnedWith ​

  • 型: (time: number, returnValue: any) => Awaitable<void>

このアサーションは、関数が特定の呼び出し回数で、特定の値を正常に返したかどうかを検証します。expect に渡されるのはスパイ関数である必要があります。

ts
import { expect, test, vi } from 'vitest';

test('スパイ関数が2回目の呼び出しで bananas を返す', () => {
  const sell = vi.fn((product: string) => ({ product }));

  sell('apples');
  sell('bananas');

  expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' });
});

toSatisfy ​

  • 型: (predicate: (value: any) => boolean) => Awaitable<void>

このアサーションは、値が特定の述語(条件)を満たしているかどうかを確認します。

ts
import { describe, expect, it } from 'vitest';
describe('toSatisfy()', () => {
  const isOdd = (value: number) => value % 2 !== 0;

  it('1 の場合に成功する', () => {
    expect(1).toSatisfy(isOdd);
  });

  it('否定形の場合に成功する', () => {
    expect(2).not.toSatisfy(isOdd);
  });
});

resolves ​

  • 型: Promisify<Assertions>

resolves は、非同期コードの検証におけるボイラープレートコードを削減することを目的としています。これを使用すると、解決済みの Promise から値を取り出し、通常のアサーションでその値を検証できます。Promise が拒否された場合、テストは失敗します。

これは同じ Assertions オブジェクトを返しますが、すべてのマッチャーが Promise を返すため、await が必要です。chai アサーションでも動作します。

たとえば、API 呼び出しを行い、何らかのデータを返す関数がある場合、次のコードを使用してその戻り値を検証できます。

ts
import { expect, test } from 'vitest';

async function buyApples() {
  return fetch('/buy/apples').then(r => r.json());
}

test('buyApples が新しい stock id を返す', async () => {
  // toEqual は Promise を返すようになったため、必ず await する必要があります
  await expect(buyApples()).resolves.toEqual({ id: 1 }); // jest API
  await expect(buyApples()).resolves.to.equal({ id: 1 }); // chai API
});

WARNING

アサーションを await しないと、毎回成功する誤検出が発生します。アサーションが実際に呼び出されるようにするには、expect.assertions(number) を使用できます。

rejects ​

  • 型: Promisify<Assertions>

rejects は、非同期コードの検証におけるボイラープレートコードを削減することを目的としています。これを使用すると、Promise が拒否された理由を取り出し、通常のアサーションでその値を検証できます。Promise が正常に解決された場合、テストは失敗します。

これは同じ Assertions オブジェクトを返しますが、すべてのマッチャーが Promise を返すため、await が必要です。chai アサーションでも動作します。

たとえば、呼び出すと失敗する関数がある場合、次のコードを使用して拒否理由を検証できます。

ts
import { expect, test } from 'vitest';

async function buyApples(id) {
  if (!id) throw new Error('no id');
}

test('buyApples は id が指定されていない場合にエラーをスローする', async () => {
  // toThrow は Promise を返すようになったため、必ず await する必要があります
  await expect(buyApples()).rejects.toThrow('no id');
});

WARNING

アサーションを await しないと、毎回成功する誤検出が発生します。アサーションが実際に呼び出されたことを確認するには、expect.assertions(number) を使用できます。

expect.assertions ​

  • 型: (count: number) => void

テストの成功/失敗に関わらず、テスト中に特定のアサーションが呼び出された回数を検証します。非同期コードが呼び出されたかどうかを確認する場合に役立ちます。

たとえば、非同期的に 2 つのマッチャーを呼び出す関数がある場合、それらが実際に呼び出されたことを検証できます。

ts
import { expect, test } from 'vitest';

async function doAsync(...cbs) {
  await Promise.all(cbs.map((cb, index) => cb({ index })));
}

test('すべてのアサーションが呼び出される', async () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }

  await doAsync(callback1, callback2);
});

WARNING

assertions を非同期の並行テストで使用する場合は、正しいテストが検出されるように、ローカルの テストコンテキスト からの expect を使用する必要があります。

expect.hasAssertions ​

  • 型: () => void

テストの成功/失敗に関わらず、テスト中に少なくとも 1 つのアサーションが呼び出されたことを検証します。非同期コードが呼び出されたかどうかを確認する場合に役立ちます。

たとえば、コールバックを呼び出すコードがある場合、コールバック内でアサーションを作成できますが、アサーションが呼び出されたかどうかを確認しないと、テストは常に成功します。

ts
import { expect, test } from 'vitest';
import { db } from './db.js';

const cbs = [];

function onSelect(cb) {
  cbs.push(cb);
}

// db から選択した後、すべてのコールバックを呼び出す
function select(id) {
  return db.select({ id }).then(data => {
    return Promise.all(cbs.map(cb => cb(data)));
  });
}

test('コールバックが呼び出された', async () => {
  expect.hasAssertions();
  onSelect(data => {
    // select で呼び出す必要がある
    expect(data).toBeTruthy();
  });
  // await しないと、テストは失敗する
  // expect.hasAssertions() がないと、テストは成功する
  await select(3);
});

expect.unreachable ​

  • 型: (message?: string) => never

このメソッドは、特定のコード行が実行されないことを検証するために使用されます。

たとえば、build() が src フォルダがないディレクトリを受け取った場合に例外をスローすることをテストし、各エラーを個別に処理したい場合、次のようにすることができます。

ts
import { expect, test } from 'vitest';

async function build(dir) {
  if (dir.includes('no-src')) throw new Error(`${dir}/src does not exist`);
}

const errorDirs = [
  'no-src-folder',
  // ...
];

test.each(errorDirs)('build が "%s" で失敗する', async dir => {
  try {
    await build(dir);
    expect.unreachable('ビルドが成功するはずがない');
  } catch (err: any) {
    expect(err).toBeInstanceOf(Error);
    expect(err.stack).toContain('build');

    switch (dir) {
      case 'no-src-folder':
        expect(err.message).toBe(`${dir}/src does not exist`);
        break;
      default:
        // すべてのエラーテストをカバーする
        expect.unreachable('すべてのエラーテストが処理されている必要がある');
        break;
    }
  }
});

expect.anything ​

  • 型: () => any

この非対称マッチャーは、等価性チェックで使用すると、常に true を返します。プロパティの存在のみを確認したい場合に役立ちます。

ts
import { expect, test } from 'vitest';

test('オブジェクトに "apples" キーがある', () => {
  expect({ apples: 22 }).toEqual({ apples: expect.anything() });
});

expect.any ​

  • 型: (constructor: unknown) => any

この非対称マッチャーは、等価性チェックで使用すると、値が指定されたコンストラクターのインスタンスである場合にのみ true を返します。毎回生成される値があり、型が適切であることのみを確認したい場合に役立ちます。

ts
import { expect, test } from 'vitest';
import { generateId } from './generators.js';

test('"id" が数値である', () => {
  expect({ id: generateId() }).toEqual({ id: expect.any(Number) });
});

expect.closeTo 1.0.0+ ​

  • 型: (expected: any, precision?: number) => any

expect.closeToは、オブジェクトのプロパティまたは配列の項目で浮動小数点数を比較する場合に役立ちます。数値を比較する必要がある場合は、代わりに.toBeCloseToを使用してください。

オプションのnumDigits引数は、小数点以下でチェックする桁数を制限します。デフォルト値2の場合、テスト基準はMath.abs(expected - received) < 0.005 (つまり、10 ** -2 / 2)です。

たとえば、次のテストは 5 桁の精度で合格します。

js
test('compare float in object properties', () => {
  expect({
    title: '0.1 + 0.2',
    sum: 0.1 + 0.2,
  }).toEqual({
    title: '0.1 + 0.2',
    sum: expect.closeTo(0.3, 5),
  });
});

expect.arrayContaining ​

  • 型: <T>(expected: T[]) => any

この非対称マッチャーは、等価性チェックで使用すると、値が配列であり、指定された項目が含まれている場合に true を返します。

ts
import { expect, test } from 'vitest';

test("バスケットに 'Fuji' が含まれている", () => {
  const basket = {
    varieties: ['Empire', 'Fuji', 'Gala'],
    count: 3,
  };
  expect(basket).toEqual({
    count: 3,
    varieties: expect.arrayContaining(['Fuji']),
  });
});

TIP

このマッチャーで expect.not を使用して、期待値を否定できます。

expect.objectContaining ​

  • 型: (expected: any) => any

この非対称マッチャーは、等価性チェックで使用すると、値が同じ構造を持つ場合に true を返します。

ts
import { expect, test } from 'vitest';

test("バスケットに 'Empire' という名前のリンゴがある", () => {
  const basket = {
    varieties: [
      {
        name: 'Empire',
        count: 1,
      },
    ],
  };
  expect(basket).toEqual({
    varieties: [expect.objectContaining({ name: 'Empire' })],
  });
});

TIP

このマッチャーで expect.not を使用して、期待値を否定できます。

expect.stringContaining ​

  • 型: (expected: any) => any

この非対称マッチャーは、等価性チェックで使用すると、値が文字列であり、指定された部分文字列が含まれている場合に true を返します。

ts
import { expect, test } from 'vitest';

test("variety の名前が 'Emp' を含む", () => {
  const variety = {
    name: 'Empire',
    count: 1,
  };
  expect(variety).toEqual({
    name: expect.stringContaining('Emp'),
    count: 1,
  });
});

TIP

このマッチャーで expect.not を使用して、期待値を否定できます。

expect.stringMatching ​

  • 型: (expected: any) => any

この非対称マッチャーは、等価性チェックで使用すると、値が文字列であり、指定された部分文字列が含まれている場合、または文字列が正規表現に一致する場合に true を返します。

ts
import { expect, test } from 'vitest';

test("variety の名前が 're' で終わる", () => {
  const variety = {
    name: 'Empire',
    count: 1,
  };
  expect(variety).toEqual({
    name: expect.stringMatching(/re$/),
    count: 1,
  });
});

TIP

このマッチャーで expect.not を使用して、期待値を否定できます。

expect.addSnapshotSerializer ​

  • 型: (plugin: PrettyFormatPlugin) => void

このメソッドは、スナップショットを作成するときに呼び出されるカスタムシリアライザーを追加します。これは高度な機能です。詳細については、カスタムシリアライザーに関するガイド を参照してください。

カスタムシリアライザーを追加する場合は、setupFiles 内でこのメソッドを呼び出す必要があります。これはすべてのスナップショットに影響します。

TIP

以前に Vue CLI を Jest で使用していた場合は、jest-serializer-vue をインストールすることをお勧めします。そうしないと、スナップショットが文字列で囲まれ、" がエスケープ処理されます。

expect.extend ​

  • 型: (matchers: MatchersObject) => void

デフォルトのマッチャーを独自のマッチャーで拡張することができます。この関数は、カスタムマッチャーでマッチャーオブジェクトを拡張するために使用されます。

そのようにマッチャーを定義すると、expect.stringContaining のように使用できる非対称マッチャーも作成されます。

ts
import { expect, test } from 'vitest';

test('カスタムマッチャー', () => {
  expect.extend({
    toBeFoo: (received, expected) => {
      if (received !== 'foo') {
        return {
          message: () => `expected '${received}' to be foo`,
          pass: false,
        };
      }
    },
  });

  expect('foo').toBeFoo();
  expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() });
});

TIP

すべてのテストでマッチャーを表示する場合は、setupFiles 内でこのメソッドを呼び出す必要があります。

この関数は Jest の expect.extend と互換性があるため、それを使用してカスタムマッチャーを作成するライブラリは Vitest で動作します。

TypeScript を使用している場合、Vitest 0.31.0 以降では、次のコードを使用して、環境宣言ファイル (例: vitest.d.ts) でデフォルトの Assertion インターフェイスを拡張できます。

ts
interface CustomMatchers<R = unknown> {
  toBeFoo: () => R;
}

declare module 'vitest' {
  interface Assertion<T = any> extends CustomMatchers<T> {}
  interface AsymmetricMatchersContaining extends CustomMatchers {}
}

WARNING

tsconfig.json に環境宣言ファイルを含めることを忘れないでください。

TIP

詳細については、マッチャーの拡張に関するガイド を確認してください。

expect.addEqualityTesters 1.2.0+ ​

  • 型: (tester: Array<Tester>) => void

このメソッドを使用すると、カスタムテスターを定義できます。これらは、2 つのオブジェクトが等しいかどうかをテストするためにマッチャーによって使用されるメソッドです。これは、Jest のexpect.addEqualityTestersと互換性があります。

ts
import { expect, test } from 'vitest';

class AnagramComparator {
  public word: string;

  constructor(word: string) {
    this.word = word;
  }

  equals(other: AnagramComparator): boolean {
    const cleanStr1 = this.word.replace(/ /g, '').toLowerCase();
    const cleanStr2 = other.word.replace(/ /g, '').toLowerCase();

    const sortedStr1 = cleanStr1.split('').sort().join('');
    const sortedStr2 = cleanStr2.split('').sort().join('');

    return sortedStr1 === sortedStr2;
  }
}

function isAnagramComparator(a: unknown): a is AnagramComparator {
  return a instanceof AnagramComparator;
}

function areAnagramsEqual(a: unknown, b: unknown): boolean | undefined {
  const isAAnagramComparator = isAnagramComparator(a);
  const isBAnagramComparator = isAnagramComparator(b);

  if (isAAnagramComparator && isBAnagramComparator) return a.equals(b);
  else if (isAAnagramComparator === isBAnagramComparator) return undefined;
  else return false;
}

expect.addEqualityTesters([areAnagramsEqual]);

test('custom equality tester', () => {
  expect(new AnagramComparator('listen')).toEqual(
    new AnagramComparator('silent')
  );
});
Pager
前のページVi
次のページexpectTypeOf

MITライセンス の下で公開されています。

Copyright (c) 2024 Mithril Contributors

https://v1.vitest.dev/api/expect

MITライセンス の下で公開されています。

Copyright (c) 2024 Mithril Contributors