メインコンテンツへスキップ
バージョン: 30.0

モック関数

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

モック関数は「スパイ」とも呼ばれます。これは出力のみをテストするのではなく、他のコードから間接的に呼び出される関数の動作を監視できるためです。モック関数はjest.fn()で作成できます。実装が指定されていない場合、呼び出されるとundefinedを返します。

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

情報

このページのTypeScriptの例は、JestのAPIを明示的にインポートした場合にのみ、ドキュメント通りに動作します:

import {expect, jest, test} from '@jest/globals';

TypeScriptでJestを設定する方法の詳細については、はじめにガイドを参照してください。

メソッド


リファレンス

mockFn.getMockName()

.mockName()の呼び出しで設定されたモック名の文字列を返します。

mockFn.mock.calls

このモック関数に対して行われたすべての呼び出しの引数を格納する配列。配列の各要素は呼び出し時に渡された引数の配列です。

例:引数f('arg1', 'arg2')で呼び出された後、f('arg3', 'arg4')で呼び出されたモック関数fmock.calls配列は次のようになります:

[
['arg1', 'arg2'],
['arg3', 'arg4'],
];

mockFn.mock.results

このモック関数に対して行われたすべての呼び出しの結果を格納する配列。各エントリはtypeプロパティとvalueプロパティを持つオブジェクトです。typeは次のいずれかになります:

  • 'return' - 通常のreturnによって呼び出しが完了したことを示します

  • 'throw' - 値のthrowによって呼び出しが完了したことを示します

  • 'incomplete' - 呼び出しがまだ完了していないことを示します(モック関数内またはモックから呼び出された関数内で結果をテストする場合に発生)

valueプロパティはthrowまたはreturnされた値を含みます。type === 'incomplete'の場合、valueはundefinedです。

例:'result1'を返し、エラーをthrowし、'result2'を返した3回呼び出されたモック関数fmock.results配列は次のようになります:

[
{
type: 'return',
value: 'result1',
},
{
type: 'throw',
value: {
/* Error instance */
},
},
{
type: 'return',
value: 'result2',
},
];

mockFn.mock.instances

newを使用してこのモック関数からインスタンス化されたすべてのオブジェクトインスタンスを含む配列。

例:2回インスタンス化されたモック関数のmock.instances配列:

const mockFn = jest.fn();

const a = new mockFn();
const b = new mockFn();

mockFn.mock.instances[0] === a; // true
mockFn.mock.instances[1] === b; // true

mockFn.mock.contexts

モック関数のすべての呼び出しに対するコンテキストを格納する配列。

コンテキストとは、関数が呼び出されたときに受け取るthisの値です。Function.prototype.bindFunction.prototype.callFunction.prototype.applyを使用して設定できます。

例:

const mockFn = jest.fn();

const boundMockFn = mockFn.bind(thisContext0);
boundMockFn('a', 'b');
mockFn.call(thisContext1, 'a', 'b');
mockFn.apply(thisContext2, ['a', 'b']);

mockFn.mock.contexts[0] === thisContext0; // true
mockFn.mock.contexts[1] === thisContext1; // true
mockFn.mock.contexts[2] === thisContext2; // true

mockFn.mock.lastCall

このモック関数に対して行われた最後の呼び出しの引数を格納する配列。関数が呼び出されていない場合はundefinedを返します。

例:引数f('arg1', 'arg2')で呼び出された後、f('arg3', 'arg4')で呼び出されたモック関数fmock.lastCall配列は次のようになります:

['arg3', 'arg4'];

mockFn.mockClear()

mockFn.mock.callsmockFn.mock.instancesmockFn.mock.contextsmockFn.mock.results配列に保存されたすべての情報をクリアします。2つのアサーション間でモックの使用データを整理する場合に便利です。

clearMocks設定オプションを使用すると、各テスト前に自動的にモックをクリアできます。

注意

mockFn.mockClear()mockFn.mock 全体を置き換えるため、単にプロパティの値をリセットするだけではないことに注意してください。そのため、古いデータにアクセスしないよう、一時的かどうかにかかわらず mockFn.mock を他の変数に代入することは避けるべきです。

mockFn.mockReset()

mockFn.mockClear() が行うすべての操作に加え、モックの実装を空の関数(undefined を返す)で置き換えます。

resetMocks 設定オプションを使用すると、各テスト前に自動的にモックをリセットできます。

mockFn.mockRestore()

mockFn.mockReset() が行うすべての操作に加え、元の(モック化されていない)実装を復元します。

特定のテストケースで関数をモック化し、他のケースでは元の実装を復元したい場合に便利です。

restoreMocks 設定オプションを使用すると、各テスト前に自動的にモックを復元できます。

情報

mockFn.mockRestore()jest.spyOn() で作成されたモックでのみ機能します。手動で jest.fn() を割り当てた場合は、自分で復元処理を行う必要があります。

mockFn.mockImplementation(fn)

モックの実装として使用する関数を受け入れます。モック自体は引き続き自身への呼び出しと生成されたインスタンスを記録しますが、呼び出されたときに実装が実行される点が異なります。

ヒント

jest.fn(implementation)jest.fn().mockImplementation(implementation) のショートカットです。

const mockFn = jest.fn(scalar => 42 + scalar);

mockFn(0); // 42
mockFn(1); // 43

mockFn.mockImplementation(scalar => 36 + scalar);

mockFn(2); // 38
mockFn(3); // 39

.mockImplementation() はクラスコンストラクタのモック化にも使用できます:

SomeClass.js
module.exports = class SomeClass {
method(a, b) {}
};
SomeClass.test.js
const SomeClass = require('./SomeClass');

jest.mock('./SomeClass'); // this happens automatically with automocking

const mockMethod = jest.fn();
SomeClass.mockImplementation(() => {
return {
method: mockMethod,
};
});

const some = new SomeClass();
some.method('a', 'b');

console.log('Calls to method:', mockMethod.mock.calls);

mockFn.mockImplementationOnce(fn)

モック関数の1回の呼び出しに対して実装として使用する関数を受け入れます。連鎖させて複数の関数呼び出しで異なる結果を生成できます。

const mockFn = jest
.fn()
.mockImplementationOnce(cb => cb(null, true))
.mockImplementationOnce(cb => cb(null, false));

mockFn((err, val) => console.log(val)); // true
mockFn((err, val) => console.log(val)); // false

モック関数が .mockImplementationOnce() で定義された実装を使い切ると、jest.fn(() => defaultValue) または .mockImplementation(() => defaultValue) で設定されたデフォルト実装を実行します:

const mockFn = jest
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');

mockFn(); // 'first call'
mockFn(); // 'second call'
mockFn(); // 'default'
mockFn(); // 'default'

mockFn.mockName(name)

テスト結果出力で 'jest.fn()' の代わりに表示する文字列を受け入れ、どのモック関数を参照しているかを示します。

例:

const mockFn = jest.fn().mockName('mockedFunction');

// mockFn();
expect(mockFn).toHaveBeenCalled();

このようなエラーが発生します:

expect(mockedFunction).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls: 0

mockFn.mockReturnThis()

省略記法:

jest.fn(function () {
return this;
});

mockFn.mockReturnValue(value)

省略記法:

jest.fn().mockImplementation(() => value);

モック関数が呼び出されたときに常に返される値を受け入れます。

const mock = jest.fn();

mock.mockReturnValue(42);
mock(); // 42

mock.mockReturnValue(43);
mock(); // 43

mockFn.mockReturnValueOnce(value)

省略記法:

jest.fn().mockImplementationOnce(() => value);

モック関数の1回の呼び出しで返される値を受け入れます。連鎖させて連続する呼び出しで異なる値を返せます。mockReturnValueOnce の値がなくなると、mockReturnValue で指定された値が返されます。

const mockFn = jest
.fn()
.mockReturnValue('default')
.mockReturnValueOnce('first call')
.mockReturnValueOnce('second call');

mockFn(); // 'first call'
mockFn(); // 'second call'
mockFn(); // 'default'
mockFn(); // 'default'

mockFn.mockResolvedValue(value)

省略記法:

jest.fn().mockImplementation(() => Promise.resolve(value));

非同期テストで非同期関数をモック化する際に便利です:

test('async test', async () => {
const asyncMock = jest.fn().mockResolvedValue(43);

await asyncMock(); // 43
});

mockFn.mockResolvedValueOnce(value)

省略記法:

jest.fn().mockImplementationOnce(() => Promise.resolve(value));

複数の非同期呼び出しで異なる値を解決する場合に便利です:

test('async test', async () => {
const asyncMock = jest
.fn()
.mockResolvedValue('default')
.mockResolvedValueOnce('first call')
.mockResolvedValueOnce('second call');

await asyncMock(); // 'first call'
await asyncMock(); // 'second call'
await asyncMock(); // 'default'
await asyncMock(); // 'default'
});

mockFn.mockRejectedValue(value)

省略記法:

jest.fn().mockImplementation(() => Promise.reject(value));

常に reject する非同期モック関数を作成する際に便利です:

test('async test', async () => {
const asyncMock = jest
.fn()
.mockRejectedValue(new Error('Async error message'));

await asyncMock(); // throws 'Async error message'
});

mockFn.mockRejectedValueOnce(value)

省略記法:

jest.fn().mockImplementationOnce(() => Promise.reject(value));

.mockResolvedValueOnce()と組み合わせて使用したり、複数の非同期呼び出しで異なる例外をスローさせたりする場合に便利です:

test('async test', async () => {
const asyncMock = jest
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error message'));

await asyncMock(); // 'first call'
await asyncMock(); // throws 'Async error message'
});

mockFn.withImplementation(fn, callback)

コールバックの実行中にモックの実装として一時的に使用する関数を受け入れます。

test('test', () => {
const mock = jest.fn(() => 'outside callback');

mock.withImplementation(
() => 'inside callback',
() => {
mock(); // 'inside callback'
},
);

mock(); // 'outside callback'
});

mockFn.withImplementationは、コールバックが非同期(thenableを返す)かどうかに関係なく使用できます。コールバックが非同期の場合、プロミスが返されます。プロミスを待機するとコールバックが実行され、実装がリセットされます。

test('async test', async () => {
const mock = jest.fn(() => 'outside callback');

// We await this call since the callback is async
await mock.withImplementation(
() => 'inside callback',
async () => {
mock(); // 'inside callback'
},
);

mock(); // 'outside callback'
});

置換されたプロパティ

replacedProperty.replaceValue(value)

既に置換されたプロパティの値を変更します。これはプロパティを置換した後、特定のテストで値を調整したい場合に便利です。代替方法として、同じプロパティに対してjest.replaceProperty()を複数回呼び出すこともできます。

replacedProperty.restore()

オブジェクトのプロパティを元の値に復元します。

replacedProperty.restore()は、プロパティ値がjest.replaceProperty()で置換された場合にのみ機能することに注意してください。

restoreMocks設定オプションを使用すると、各テスト前に置換されたプロパティを自動的に復元できます。

TypeScript 使用方法

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

情報

このページのTypeScriptの例は、JestのAPIを明示的にインポートした場合にのみ、ドキュメント通りに動作します:

import {expect, jest, test} from '@jest/globals';

TypeScriptでJestを設定する方法の詳細については、はじめにガイドを参照してください。

jest.fn(implementation?)

実装がjest.fn()に渡されると、正しいモックの型推論が行われます。実装が省略される多くのユースケースがあります。型安全性を確保するためにはジェネリック型引数を渡すことができます(詳細は上記の例も参照):

import {expect, jest, test} from '@jest/globals';
import type add from './add';
import calculate from './calc';

test('calculate calls add', () => {
// Create a new mock that can be used in place of `add`.
const mockAdd = jest.fn<typeof add>();

// `.mockImplementation()` now can infer that `a` and `b` are `number`
// and that the returned value is a `number`.
mockAdd.mockImplementation((a, b) => {
// Yes, this mock is still adding two numbers but imagine this
// was a complex function we are mocking.
return a + b;
});

// `mockAdd` is properly typed and therefore accepted by anything
// requiring `add`.
calculate(mockAdd, 1, 2);

expect(mockAdd).toHaveBeenCalledTimes(1);
expect(mockAdd).toHaveBeenCalledWith(1, 2);
});

jest.Mock<T>

モック関数の型を構築します(例: jest.fn()の戻り値型)。再帰的なモック関数を定義する必要がある場合に便利です:

import {jest} from '@jest/globals';

const sumRecursively: jest.Mock<(value: number) => number> = jest.fn(value => {
if (value === 0) {
return 0;
} else {
return value + fn(value - 1);
}
});

jest.Mocked<Source>

jest.Mocked<Source>ユーティリティ型は、Jestモック関数の型定義でラップされたSource型を返します。

import {expect, jest, test} from '@jest/globals';
import type {fetch} from 'node-fetch';

jest.mock('node-fetch');

let mockedFetch: jest.Mocked<typeof fetch>;

afterEach(() => {
mockedFetch.mockClear();
});

test('makes correct call', () => {
mockedFetch = getMockedFetch();
// ...
});

test('returns correct data', () => {
mockedFetch = getMockedFetch();
// ...
});

クラス、関数、オブジェクトの型をjest.Mocked<Source>の型引数として渡せます。入力型を制限したい場合は、jest.MockedClass<Source>jest.MockedFunction<Source>jest.MockedObject<Source>を使用してください。

jest.Replaced<Source>

jest.Replaced<Source>ユーティリティ型は、Jestの置換プロパティの型定義でラップされたSource型を返します。

src/utils.ts
export function isLocalhost(): boolean {
return process.env['HOSTNAME'] === 'localhost';
}
src/__tests__/utils.test.ts
import {afterEach, expect, it, jest} from '@jest/globals';
import {isLocalhost} from '../utils';

let replacedEnv: jest.Replaced<typeof process.env> | undefined = undefined;

afterEach(() => {
replacedEnv?.restore();
});

it('isLocalhost should detect localhost environment', () => {
replacedEnv = jest.replaceProperty(process, 'env', {HOSTNAME: 'localhost'});

expect(isLocalhost()).toBe(true);
});

it('isLocalhost should detect non-localhost environment', () => {
replacedEnv = jest.replaceProperty(process, 'env', {HOSTNAME: 'example.com'});

expect(isLocalhost()).toBe(false);
});

jest.mocked(source, options?)

mocked()ヘルパーメソッドは、sourceオブジェクトとその深くネストされたメンバーの型をJestモック関数の型定義でラップします。{shallow: true}options引数として渡すと、深いモックの動作を無効にできます。

sourceオブジェクトを返します。

song.ts
export const song = {
one: {
more: {
time: (t: number) => {
return t;
},
},
},
};
song.test.ts
import {expect, jest, test} from '@jest/globals';
import {song} from './song';

jest.mock('./song');
jest.spyOn(console, 'log');

const mockedSong = jest.mocked(song);
// or through `jest.Mocked<Source>`
// const mockedSong = song as jest.Mocked<typeof song>;

test('deep method is typed correctly', () => {
mockedSong.one.more.time.mockReturnValue(12);

expect(mockedSong.one.more.time(10)).toBe(12);
expect(mockedSong.one.more.time.mock.calls).toHaveLength(1);
});

test('direct usage', () => {
jest.mocked(console.log).mockImplementation(() => {
return;
});

console.log('one more time');

expect(jest.mocked(console.log).mock.calls).toHaveLength(1);
});

jest.Spied<Source>

スパイされたクラスまたは関数の型を構築します(例: jest.spyOn()の戻り値型)。

__utils__/setDateNow.ts
import {jest} from '@jest/globals';

export function setDateNow(now: number): jest.Spied<typeof Date.now> {
return jest.spyOn(Date, 'now').mockReturnValue(now);
}
import {afterEach, expect, type jest, test} from '@jest/globals';
import {setDateNow} from './__utils__/setDateNow';

let spiedDateNow: jest.Spied<typeof Date.now> | undefined = undefined;

afterEach(() => {
spiedDateNow?.mockReset();
});

test('renders correctly with a given date', () => {
spiedDateNow = setDateNow(1_482_363_367_071);
// ...

expect(spiedDateNow).toHaveBeenCalledTimes(1);
});

クラスまたは関数の型をjest.Spied<Source>の型引数として渡せます。入力型を制限したい場合は、jest.SpiedClass<Source>またはjest.SpiedFunction<Source>を使用してください。

それぞれスパイされたゲッターまたはセッターの型を作成するには、jest.SpiedGetter<Source>またはjest.SpiedSetter<Source>を使用してください。