expect
以下に、最適化された翻訳内容を出力します。
type Awaitable<T> = T | PromiseLike<T>;
expect
はアサーションを作成するために使用されます。この文脈では、アサーション
とは、ステートメントを検証するために呼び出される関数を指します。Vitest はデフォルトで chai
アサーションを提供し、chai
を基盤とした Jest
互換のアサーションも提供します。Jest
とは異なり、Vitest は2番目の引数としてエラーメッセージをサポートしています。アサーションが失敗した場合、このメッセージがエラーとして表示されます。
export interface ExpectStatic
extends Chai.ExpectStatic,
AsymmetricMatchersContaining {
<T>(actual: T, message?: string): Assertion<T>;
extend: (expects: MatchersObject) => void;
anything: () => any;
any: (constructor: unknown) => any;
getState: () => MatcherState;
setState: (state: Partial<MatcherState>) => void;
not: AsymmetricMatchersContaining;
}
例えば、このコードは input
の値が 2
と等しいことを検証します。等しくない場合、アサーションはエラーをスローし、テストは失敗します。
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
の詳細については、Test API Reference を参照してください。
また、expect
は後述するマッチャー関数への静的アクセスにも使用されます。
WARNING
expect
は、式に型エラーがない場合、型チェックに影響を与えません。Vitest を 型チェッカー として使用したい場合は、expectTypeOf
または assertType
を使用してください。
soft
- 型:
ExpectStatic & (actual: any) => Assertions
expect.soft
は expect
と同様に機能しますが、アサーションが失敗してもテストの実行を終了せず、実行を継続し、テストを失敗として記録します。テスト中に発生したすべてのエラーは、テストが完了するまで報告されます。
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // テストを失敗としてマークし、続行
expect.soft(1 + 2).toBe(4); // テストを失敗としてマークし、続行
});
// レポーターは実行終了時に両方のエラーを報告します
expect
と一緒に使用することもできます。expect
アサーションが失敗した場合、テストは終了し、それまでに発生したすべてのエラーが出力されます。
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
関数内でのみ使用できます。
poll
interface ExpectPoll extends ExpectStatic {
(actual: () => T, options: { interval; timeout; message }): Promise<
Assertions<T>
>;
}
expect.poll
は、アサーションが成功するまで再試行します。interval
および timeout
オプションを設定することで、Vitest が expect.poll
コールバックを再実行する間隔と最大時間を設定できます。
expect.poll
コールバック内でエラーがスローされた場合、Vitest はタイムアウトになるまで再試行します。
import { expect, test } from 'vitest';
test('element exists', async () => {
asyncInjectElement();
await expect.poll(() => document.querySelector('.element')).toBeTruthy();
});
WARNING
expect.poll
はすべてのアサーションが非同期であるため、await
する必要があります。Vitest 3 以降、await
を忘れると警告が表示され、テストは失敗します。
expect.poll
はいくつかのマッチャーでは機能しません。
- スナップショットマッチャーは常に成功するためサポート対象外です。条件が不安定な場合は、代わりに
vi.waitFor
を使用して最初に解決することを検討してください。
import { expect, vi } from 'vitest';
const flakyValue = await vi.waitFor(() => getFlakyValue());
expect(flakyValue).toMatchSnapshot();
.resolves
と.rejects
はサポートされていません。expect.poll
は、条件が非同期の場合、すでに待機しています。toThrow
とそのエイリアスはサポートされていません。expect.poll
の条件は、マッチャーが値を取得する前に常に解決されるためです。
not
not
を使用すると、アサーションが否定されます。例えば、このコードは input
の値が 2
と等しくないことを検証します。等しい場合、アサーションはエラーをスローし、テストは失敗します。
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個持っているかをチェックします。
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; // 同じ参照
expect(stock).toBe(refStock);
});
浮動小数点数で toBe
を使用しないようにしてください。JavaScript はそれらを丸め処理を行うため、0.1 + 0.2
は厳密には 0.3
ではありません。浮動小数点数を確実にアサートするには、toBeCloseTo
アサーションを使用してください。
toBeCloseTo
- 型:
(value: number, numDigits?: number) => Awaitable<void>
浮動小数点数を比較するには toBeCloseTo
を使用します。オプションの numDigits
引数は、小数点_以下_でチェックする桁数を制限します。例:
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 は 0.30000000000000004
});
test('decimals are rounded to 5 after the point', () => {
// 0.2 + 0.1 は 0.30000 | "000000000004" は削除されます
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
// 0.30000000000000004 から何も削除されません
expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50);
});
toBeDefined
- 型:
() => Awaitable<void>
toBeDefined
は、値が undefined
と等しくないことをアサートします。関数が値を_返した_かどうかをチェックするのに役立ちます。
import { expect, test } from 'vitest';
function getApples() {
return 3;
}
test('function returned something', () => {
expect(getApples()).toBeDefined();
});
toBeUndefined
- 型:
() => Awaitable<void>
toBeDefined
の反対で、toBeUndefined
は値が undefined
と_等しい_ことをアサートします。関数が何も値を_返さなかった_かどうかをチェックするのに役立ちます。
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
は、値が boolean に変換されたときに true であることをアサートします。値自体には関心がなく、true
に変換できるかどうかだけを確認したい場合に便利です。
例えば、このコードでは stocks.getInfo
の戻り値には関心がありません。それは複雑なオブジェクト、文字列、またはその他のものでも構いません。コードは引き続き機能します。
import { Stocks } from './stocks.js';
const stocks = new Stocks();
stocks.sync('Bill');
if (stocks.getInfo('Bill')) {
stocks.sell('apples', 'Bill');
}
したがって、stocks.getInfo
が truthy であることをテストしたい場合は、次のように書くことができます。
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
は、値が boolean に変換されたときに false であることをアサートします。値自体には関心がなく、false
に変換できるかどうかだけを確認したい場合に便利です。
例えば、このコードでは stocks.stockFailed
の戻り値には関心がありません。それは falsy な値を返すかもしれませんが、コードは引き続き機能します。
import { Stocks } from './stocks.js';
const stocks = new Stocks();
stocks.sync('Bill');
if (!stocks.stockFailed('Bill')) {
stocks.sell('apples', 'Bill');
}
したがって、stocks.stockFailed
が falsy であることをテストしたい場合は、次のように書くことができます。
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)
のエイリアスです。
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)
のエイリアスです。
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();
});
toBeOneOf
- 型:
(sample: Array<any>) => any
toBeOneOf
は、値が提供された配列内のいずれかの値と一致するかどうかをアサートします。
import { expect, test } from 'vitest';
test('fruit is one of the allowed values', () => {
expect(fruit).toBeOneOf(['apple', 'banana', 'orange']);
});
非対称マッチャーは、null
または undefined
のいずれかになりうるオプションのプロパティをテストする場合に特に便利です。
test('optional properties can be null or undefined', () => {
const user = {
firstName: 'John',
middleName: undefined,
lastName: 'Doe',
};
expect(user).toEqual({
firstName: expect.any(String),
middleName: expect.toBeOneOf([expect.any(String), undefined]),
lastName: expect.any(String),
});
});
TIP
このマッチャーで expect.not
を使用して、値が提供されたオプションのいずれとも一致しないことを確認できます。
toBeTypeOf
- 型:
(c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>
toBeTypeOf
は、実際の値が受け取った型の型であるかどうかをアサートします。
import { expect, test } from 'vitest';
const actual = 'stock';
test('stock is type of string', () => {
expect(actual).toBeTypeOf('string');
});
toBeInstanceOf
- 型:
(c: any) => Awaitable<void>
toBeInstanceOf
は、実際の値が受け取ったクラスのインスタンスであるかどうかをアサートします。
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
は、実際の値が受け取った値より大きいことをアサートします。等しい場合はテストが失敗します。
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
は、実際の値が受け取った値より大きいか、または等しいかをアサートします。
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
は、実際の値が受け取った値より小さいことをアサートします。等しい値はテストを失敗させます。
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
は、実際の値が受け取った値より小さいか、または等しいかをアサートします。
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
の違いは、この例で確認できます。
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
オブジェクトの場合、name
、message
、cause
、AggregateError.errors
などの列挙不可能なプロパティも比較対象となります。Error.cause
の場合、比較は非対称に行われます。
// 成功
expect(new Error('hi', { cause: 'x' })).toEqual(new Error('hi'));
// 失敗
expect(new Error('hi')).toEqual(new Error('hi', { cause: 'x' }));
何かがスローされたことをテストするには、toThrowError
アサーションを使用します。
toStrictEqual
- 型:
(received: any) => Awaitable<void>
toStrictEqual
は、実際の値が受け取った値と等しいか、またはオブジェクトであれば同じ構造を持つか(再帰的に比較します)、そして同じ型であるかをアサートします。
.toEqual
との違い:
undefined
プロパティを持つキーがチェックされます。例:{a: undefined, b: 2}
は.toStrictEqual
を使用した場合、{b: 2}
と一致しないと判断されます。- 配列の疎性がチェックされます。例:
[, 1]
は.toStrictEqual
を使用した場合、[undefined, 1]
と一致しないと判断されます。 - オブジェクトの型が等しいかどうかがチェックされます。例:フィールド
a
とb
を持つクラスインスタンスは、フィールドa
とb
を持つリテラルオブジェクトとは等しいとは見なされません。
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
は、文字列が別の文字列の部分文字列であるかどうかも確認できます。ブラウザのような環境でテストを実行している場合、このアサーションは、クラスが classList
に含まれているか、または要素が別の要素内にあるかどうかもチェックできます。
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');
// 要素にクラスがある
expect(element.classList).toContain('flex');
// 要素が別の要素内にある
expect(document.querySelector('#wrapper')).toContain(element);
});
toContainEqual
- 型:
(received: any) => Awaitable<void>
toContainEqual
は、特定の構造と値を持つ項目が配列に含まれているかどうかをアサートします。 各要素に対して内部的に toEqual
のように機能します。
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
プロパティを持ち、それが特定の数値に設定されていることをアサートします。
import { expect, test } from 'vitest';
test('toHaveLength', () => {
expect('abc').toHaveLength(3);
expect([1, 2, 3]).toHaveLength(3);
expect('').not.toHaveLength(3); // .length が 3 ではない
expect({ length: 3 }).toHaveLength(3);
});
toHaveProperty
- 型:
(key: any, received?: any) => Awaitable<void>
toHaveProperty
は、提供された参照 key
にプロパティがオブジェクトに存在することをアサートします。
オプションで値引数(ディープ等価性とも呼ばれます)を提供することも可能で、toEqual
マッチャーのように受け取ったプロパティ値を比較します。
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
- 型:
(received: string | regexp) => Awaitable<void>
toMatch
は、文字列が正規表現または文字列と一致することをアサートします。
import { expect, test } from 'vitest';
test('top fruits', () => {
expect('top fruits include apple, orange and grape').toMatch(/apple/);
expect('applefruits').toMatch('fruit'); // toMatch は文字列も受け入れます
});
toMatchObject
- 型:
(received: object | array) => Awaitable<void>
toMatchObject
は、オブジェクトがオブジェクトのプロパティのサブセットと一致することをアサートします。
オブジェクトの配列を渡すこともできます。これは、2つの配列が要素数で一致するかどうかを確認したい場合に便利です。arrayContaining
は、受け取った配列に余分な要素を許可します。
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
型:
(received: any) => Awaitable<void>
エイリアス:
toThrow
toThrowError
は、関数が呼び出されたときにエラーをスローすることをアサートします。
特定のエラーがスローされたことをテストするために、オプションの引数を提供できます。
RegExp
: エラーメッセージがパターンと一致するstring
: エラーメッセージに部分文字列が含まれるError
,AsymmetricMatcher
:toEqual(received)
と同様に、受け取ったオブジェクトと比較する
TIP
コードを関数でラップする必要があります。そうしない場合、エラーがキャッチされず、テストが失敗します。
これは、rejects がプロミスを正しくアンラップするため、非同期呼び出しには適用されません。
test('expect rejects toThrow', async ({ expect }) => {
const promise = Promise.reject(new Error('Test'));
await expect(promise).rejects.toThrowError();
});
例えば、getFruitStock('pineapples')
がスローすることをテストしたい場合、次のように書くことができます。
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$/
);
expect(() => getFruitStock('pineapples')).toThrowError(
new Error('Pineapples are not in stock')
);
expect(() => getFruitStock('pineapples')).toThrowError(
expect.objectContaining({
message: 'Pineapples are not in stock',
})
);
});
TIP
非同期関数をテストするには、rejects と組み合わせて使用します。
function getAsyncFruitStock() {
return Promise.reject(new Error('empty'));
}
test('throws on pineapples', async () => {
await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty');
});
toMatchSnapshot
- 型:
<T>(shape?: Partial<T> | string, hint?: string) => void
これは、値が最新のスナップショットと一致することを検証します。
オプションの hint
文字列引数を指定できます。これはテスト名に追加されます。Vitest は常にスナップショット名の末尾に数字を追加しますが、短い説明的なヒントは、単一の it
または test
ブロック内の複数のスナップショットを区別するのに数字よりも有用な場合があります。Vitest は、対応する .snap
ファイル内でスナップショットを名前でソートします。
TIP
スナップショットが一致せずテストが失敗した場合、その不一致が予期されたものである場合は、u
キーを押してスナップショットを更新できます。または、-u
または --update
CLI オプションを渡して、Vitest が常にテストを更新するようにすることもできます。
import { expect, test } from 'vitest';
test('matches snapshot', () => {
const data = { foo: new Set(['bar', 'snapshot']) };
expect(data).toMatchSnapshot();
});
オブジェクトの形状のみをテストしていて、100%互換性がある必要がない場合は、オブジェクトの形状を提供することもできます。
import { expect, test } from 'vitest';
test('matches snapshot', () => {
const data = { foo: new Set(['bar', 'snapshot']) };
expect(data).toMatchSnapshot({ foo: expect.any(Set) });
});
toMatchInlineSnapshot
- 型:
<T>(shape?: Partial<T> | string, snapshot?: string, hint?: string) => void
これは、値が最新のスナップショットと一致することを検証します。
Vitest は、テストファイル内のマッチャーに inlineSnapshot 文字列引数を追加および更新します(外部の .snap
ファイルではなく)。
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%互換性がある必要がない場合は、オブジェクトの形状を提供することもできます。
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
- 型:
<T>(filepath: string, hint?: string) => Promise<void>
スナップショットを明示的に指定されたファイルの内容と比較または更新します(.snap
ファイルではなく)。
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
を使用する必要があります。await
が使用されない場合、Vitest はそれを expect.soft
のように扱い、スナップショットが一致しなくてもステートメントの後のコードは実行が継続されます。テストが終了した後、Vitest はスナップショットをチェックし、不一致がある場合は失敗します。
toThrowErrorMatchingSnapshot
- 型:
(hint?: string) => void
toMatchSnapshot
と同じですが、toThrowError
と同じ値を期待します。
toThrowErrorMatchingInlineSnapshot
- 型:
(snapshot?: string, hint?: string) => void
toMatchInlineSnapshot
と同じですが、toThrowError
と同じ値を期待します。
toHaveBeenCalled
- 型:
() => Awaitable<void>
このアサーションは、関数が呼び出されたことのテストに役立ちます。expect
にスパイ関数を渡す必要があります。
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
- 型:
(amount: number) => Awaitable<void>
このアサーションは、関数が特定の回数呼び出されたかどうかを確認します。expect
にスパイ関数を渡す必要があります。
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
- 型:
(...args: any[]) => Awaitable<void>
このアサーションは、関数が特定のパラメータで少なくとも1回呼び出されたかどうかを確認します。expect
にスパイ関数を渡す必要があります。
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);
});
toHaveBeenCalledBefore 3.0.0+
- 型:
(mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>
このアサーションは、ある Mock
が別の Mock
の前に呼び出されたかどうかを確認します。
test('calls mock1 before mock2', () => {
const mock1 = vi.fn();
const mock2 = vi.fn();
mock1();
mock2();
mock1();
expect(mock1).toHaveBeenCalledBefore(mock2);
});
toHaveBeenCalledAfter 3.0.0+
- 型:
(mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>
このアサーションは、ある Mock
が別の Mock
の後に呼び出されたかどうかを確認します。
test('calls mock1 after mock2', () => {
const mock1 = vi.fn();
const mock2 = vi.fn();
mock2();
mock1();
mock2();
expect(mock1).toHaveBeenCalledAfter(mock2);
});
toHaveBeenCalledExactlyOnceWith 3.0.0+
- 型:
(...args: any[]) => Awaitable<void>
このアサーションは、関数が正確に1回、かつ特定のパラメータで呼び出されたかどうかを確認します。expect
にスパイ関数を渡す必要があります。
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);
expect(buySpy).toHaveBeenCalledExactlyOnceWith('apples', 10);
});
toHaveBeenLastCalledWith
- 型:
(...args: any[]) => Awaitable<void>
このアサーションは、関数が最後の呼び出しで特定のパラメータで呼び出されたかどうかを確認します。expect
にスパイ関数を渡す必要があります。
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
- 型:
(time: number, ...args: any[]) => Awaitable<void>
このアサーションは、関数が特定の回数目に特定のパラメータで呼び出されたかどうかを確認します。カウントは1から始まります。したがって、2番目のエントリをチェックするには、.toHaveBeenNthCalledWith(2, ...)
と記述します。
expect
にスパイ関数を渡す必要があります。
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
- 型:
() => Awaitable<void>
このアサーションは、関数が少なくとも1回正常に値を返したかどうか(つまり、エラーをスローしなかったかどうか)を確認します。expect
にスパイ関数を渡す必要があります。
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
- 型:
(amount: number) => Awaitable<void>
このアサーションは、関数が正確な回数だけ正常に値を返したかどうか(つまり、エラーをスローしなかったかどうか)を確認します。expect
にスパイ関数を渡す必要があります。
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>
このアサーションを呼び出して、関数が特定のパラメータで少なくとも1回正常に値を返したかどうかを確認できます。expect
にスパイ関数を渡す必要があります。
import { expect, test, vi } from 'vitest';
test('spy function returns a product', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
expect(sell).toHaveReturnedWith({ product: 'apples' });
});
toHaveLastReturnedWith
- 型:
(returnValue: any) => Awaitable<void>
このアサーションを呼び出して、関数が最後に呼び出されたときに特定の値を正常に返したかどうかを確認できます。expect
にスパイ関数を渡す必要があります。
import { expect, test, vi } from 'vitest';
test('spy function returns bananas on a last call', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});
toHaveNthReturnedWith
- 型:
(time: number, returnValue: any) => Awaitable<void>
このアサーションを呼び出して、関数が特定の呼び出しで特定のパラメータで正常に値を返したかどうかを確認できます。expect
にスパイ関数を渡す必要があります。
import { expect, test, vi } from 'vitest';
test('spy function returns bananas on second call', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' });
});
toHaveResolved
- 型:
() => Awaitable<void>
このアサーションは、関数が少なくとも1回正常に値を解決したかどうか(つまり、拒否されなかったかどうか)を確認します。expect
にスパイ関数を渡す必要があります。
関数がプロミスを返したが、まだ解決されていない場合、これは失敗します。
import { expect, test, vi } from 'vitest';
import db from './db/apples.js';
async function getApplesPrice(amount: number) {
return amount * (await db.get('price'));
}
test('spy function resolved a value', async () => {
const getPriceSpy = vi.fn(getApplesPrice);
const price = await getPriceSpy(10);
expect(price).toBe(100);
expect(getPriceSpy).toHaveResolved();
});
toHaveResolvedTimes
- 型:
(amount: number) => Awaitable<void>
このアサーションは、関数が正確な回数だけ正常に値を解決したかどうか(つまり、拒否されなかったかどうか)を確認します。expect
にスパイ関数を渡す必要があります。
これは解決されたプロミスのみをカウントします。関数がプロミスを返したが、まだ解決されていない場合、カウントされません。
import { expect, test, vi } from 'vitest';
test('spy function resolved a value two times', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('apples');
await sell('bananas');
expect(sell).toHaveResolvedTimes(2);
});
toHaveResolvedWith
- 型:
(returnValue: any) => Awaitable<void>
このアサーションを呼び出して、関数が少なくとも1回特定の値を正常に解決したかどうかを確認できます。expect
にスパイ関数を渡す必要があります。
関数がプロミスを返したが、まだ解決されていない場合、これは失敗します。
import { expect, test, vi } from 'vitest';
test('spy function resolved a product', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('apples');
expect(sell).toHaveResolvedWith({ product: 'apples' });
});
toHaveLastResolvedWith
- 型:
(returnValue: any) => Awaitable<void>
このアサーションを呼び出して、関数が最後に呼び出されたときに特定の値を正常に解決したかどうかを確認できます。expect
にスパイ関数を渡す必要があります。
関数がプロミスを返したが、まだ解決されていない場合、これは失敗します。
import { expect, test, vi } from 'vitest';
test('spy function resolves bananas on a last call', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('apples');
await sell('bananas');
expect(sell).toHaveLastResolvedWith({ product: 'bananas' });
});
toHaveNthResolvedWith
- 型:
(time: number, returnValue: any) => Awaitable<void>
このアサーションを呼び出して、関数が特定の呼び出しで特定の値を正常に解決したかどうかを確認できます。expect
にスパイ関数を渡す必要があります。
関数がプロミスを返したが、まだ解決されていない場合、これは失敗します。
import { expect, test, vi } from 'vitest';
test('spy function returns bananas on second call', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('apples');
await sell('bananas');
expect(sell).toHaveNthResolvedWith(2, { product: 'bananas' });
});
toSatisfy
- 型:
(predicate: (value: any) => boolean) => Awaitable<void>
このアサーションは、値が特定の述語を満たすかどうかを検証します。
import { describe, expect, it } from 'vitest';
const isOdd = (value: number) => value % 2 !== 0;
describe('toSatisfy()', () => {
it('pass with 0', () => {
expect(1).toSatisfy(isOdd);
});
it('pass with negation', () => {
expect(2).not.toSatisfy(isOdd);
});
});
resolves
- 型:
Promisify<Assertions>
resolves
は、非同期コードをアサートする際の定型文を削減することを目的としています。保留中のプロミスから値をアンラップし、通常のアサーションでその値を検証するために使用します。プロミスが拒否された場合、アサーションは失敗します。
同じ Assertions
オブジェクトを返しますが、すべてのマッチャーが Promise
を返すため、await
する必要があります。chai
アサーションでも機能します。
例えば、API呼び出しを行い、データを返す関数がある場合、このコードを使用してその戻り値を検証できます。
import { expect, test } from 'vitest';
async function buyApples() {
return fetch('/buy/apples').then(r => r.json());
}
test('buyApples returns new stock id', async () => {
// toEqual はプロミスを返すため、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)
を利用できます。
Vitest 3 以降、メソッドが await
されない場合、Vitest はテストの最後に警告が表示されるようになります。Vitest 4 では、アサーションが await
されない場合、テストは「失敗」としてマークされます。
rejects
- 型:
Promisify<Assertions>
rejects
は、非同期コードをアサートする際の定型的な記述を減らすことを目的としています。プロミスが拒否された理由をアンラップし、通常のアサーションでその値をアサートするために利用します。プロミスが正常に解決された場合、アサーションは失敗と判断されます。
同じ Assertions
オブジェクトを返しますが、すべてのマッチャーが Promise
を返すため、await
する必要があります。chai
アサーションでも機能します。
例えば、呼び出すと失敗する関数がある場合、このコードを使用してその理由をアサートできます。
import { expect, test } from 'vitest';
async function buyApples(id) {
if (!id) {
throw new Error('no id');
}
}
test('buyApples throws an error when no id provided', async () => {
// toThrow はプロミスを返すため、await する必要があります
await expect(buyApples()).rejects.toThrow('no id');
});
WARNING
アサーションが await
されない場合、常にパスする偽陽性テストとなってしまいます。アサーションが実際に呼び出されたことを確認するには、expect.assertions(number)
を利用できます。
Vitest 3 以降、メソッドが await
されない場合、Vitest はテストの最後に警告が表示されるようになります。Vitest 4 では、アサーションが await
されない場合、テストは「失敗」としてマークされます。
expect.assertions
- 型:
(count: number) => void
テストがパスまたは失敗した後、テスト中に特定のアサーション数が呼び出されたことを検証します。非同期コードが呼び出されたかどうかを確認するのに役立ちます。
例えば、非同期に2つのマッチャーを呼び出す関数がある場合、それらが実際に呼び出されたことをアサートできます。
import { expect, test } from 'vitest';
async function doAsync(...cbs) {
await Promise.all(cbs.map((cb, index) => cb({ index })));
}
test('all assertions are called', async () => {
expect.assertions(2);
function callback1(data) {
expect(data).toBeTruthy();
}
function callback2(data) {
expect(data).toBeTruthy();
}
await doAsync(callback1, callback2);
});
WARNING
非同期の並行テストで assertions
を使用する場合、正しいテストが検出されるように、ローカルの Test Context からの expect
を使用する必要があります。
expect.hasAssertions
- 型:
() => void
テストがパスまたは失敗した後、テスト中に少なくとも1つのアサーションが呼び出されたことを検証します。非同期コードが呼び出されたかどうかを確認するのに役立ちます。
例えば、コールバックを呼び出すコードがある場合、コールバック内でアサーションを行うことができますが、アサーションが呼び出されたかどうかを確認しないと、テストは常にパスします。
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('callback was called', async () => {
expect.hasAssertions();
onSelect(data => {
// 選択時に呼び出されるべき
expect(data).toBeTruthy();
});
// await しないとテストは失敗します
// expect.hasAssertions() がないとテストはパスします
await select(3);
});
expect.unreachable
- 型:
(message?: string) => never
このメソッドは、ある行に到達してはならないことをアサートするために利用されます。
例えば、src
フォルダーのないディレクトリを受け取ったために build()
がエラーをスローし、各エラーを個別に処理することをテストしたい場合、次のようにすることができます。
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 fails with "%s"', async dir => {
try {
await build(dir);
expect.unreachable('Should not pass build');
} 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('All error test must be handled');
break;
}
}
});
expect.anything
- 型:
() => any
この非対称マッチャーは、等価性チェックで使用されると常に true
を返します。プロパティが存在することを確認するのに便利です。
import { expect, test } from 'vitest';
test('object has "apples" key', () => {
expect({ apples: 22 }).toEqual({ apples: expect.anything() });
});
expect.any
- 型:
(constructor: unknown) => any
この非対称マッチャーは、等価性チェックで使用されると、値が指定されたコンストラクタのインスタンスである場合にのみ true
を返します。値が毎回生成され、適切な型で存在することだけを確認したい場合に便利です。
import { expect, test } from 'vitest';
import { generateId } from './generators.js';
test('"id" is a number', () => {
expect({ id: generateId() }).toEqual({ id: expect.any(Number) });
});
expect.closeTo
- 型:
(expected: any, precision?: number) => any
expect.closeTo
は、オブジェクトのプロパティや配列の項目で浮動小数点数を比較する際に便利です。数値を比較する必要がある場合は、代わりに .toBeCloseTo
を利用してください。
オプションの precision
引数は、小数点以下でチェックする桁数を制限します。デフォルト値 2
の場合、テスト基準は Math.abs(expected - received) < 0.005 (つまり、10 ** -2 / 2)
です。
例えば、このテストは精度5桁でパスします。
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
を返します。
import { expect, test } from 'vitest';
test('basket includes 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
を返します。
import { expect, test } from 'vitest';
test('basket has empire apples', () => {
const basket = {
varieties: [
{
name: 'Empire',
count: 1,
},
],
};
expect(basket).toEqual({
varieties: [expect.objectContaining({ name: 'Empire' })],
});
});
TIP
このマッチャーで expect.not
を使用して、期待される値を否定できます。
expect.stringContaining
- 型:
(expected: any) => any
等価性チェックで使用されると、この非対称マッチャーは、値が文字列であり、指定された部分文字列が含まれている場合に true
を返します。
import { expect, test } from 'vitest';
test('variety has "Emp" in its name', () => {
const variety = {
name: 'Empire',
count: 1,
};
expect(variety).toEqual({
name: expect.stringContaining('Emp'),
count: 1,
});
});
TIP
このマッチャーで expect.not
を使用して、期待される値を否定できます。
expect.stringMatching
- 型:
(expected: any) => any
等価性チェックで使用されると、この非対称マッチャーは、値が文字列であり、指定された部分文字列が含まれているか、または文字列が正規表現と一致する場合に true
を返します。
import { expect, test } from 'vitest';
test('variety ends with "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
以前に Jest で Vue CLI を使用していた場合、jest-serializer-vue をインストールすることをお勧めします。そうしないと、スナップショットが文字列でラップされ、"
がエスケープされる原因となります。
expect.extend
- 型:
(matchers: MatchersObject) => void
デフォルトのマッチャーを独自のマッチャーで拡張することが可能です。この関数は、カスタムマッチャーでマッチャーオブジェクトを拡張するために利用されます。
このようにマッチャーを定義すると、expect.stringContaining
のように使用できる非対称マッチャーも作成されます。
import { expect, test } from 'vitest';
test('custom matchers', () => {
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
インターフェースを拡張できます。
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
- 型:
(tester: Array<Tester>) => void
このメソッドを使用して、カスタムテスターを定義することが可能です。これは、2つのオブジェクトが等しいかどうかをテストするためにマッチャーが利用するメソッドです。Jest の expect.addEqualityTesters
と互換性があります。
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')
);
});