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

非同期処理の例

非公式ベータ版翻訳

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

まず、Getting Startedガイドに記載されている通り、JestでBabelサポートを有効にしてください。

APIからユーザーデータを取得しユーザー名を返すモジュールを実装してみましょう。

user.js
import request from './request';

export function getUserName(userID) {
return request(`/users/${userID}`).then(user => user.name);
}

上記の実装では、request.jsモジュールがPromiseを返すことを想定しています。ユーザー名を受け取るためにthenをチェーンします。

次に、ネットワーク経由でユーザーデータを取得するrequest.jsの実装例を考えてみましょう:

request.js
const http = require('http');

export default function request(url) {
return new Promise(resolve => {
// This is an example of an http request, for example to fetch
// user data from an API.
// This module is being mocked in __mocks__/request.js
http.get({path: url}, response => {
let data = '';
response.on('data', _data => (data += _data));
response.on('end', () => resolve(data));
});
});
}

テストで実際のネットワーク接続を行いたくないため、__mocks__フォルダにrequest.jsの手動モックを作成します(フォルダ名は大文字小文字を区別するため、__MOCKS__は機能しません)。例は以下のようになります:

__mocks__/request.js
const users = {
4: {name: 'Mark'},
5: {name: 'Paul'},
};

export default function request(url) {
return new Promise((resolve, reject) => {
const userID = parseInt(url.slice('/users/'.length), 10);
process.nextTick(() =>
users[userID]
? resolve(users[userID])
: reject({
error: `User with ${userID} not found.`,
}),
);
});
}

では、非同期機能のテストを記述しましょう。

__tests__/user-test.js
jest.mock('../request');

import * as user from '../user';

// The assertion for a promise must be returned.
it('works with promises', () => {
expect.assertions(1);
return user.getUserName(4).then(data => expect(data).toBe('Mark'));
});

jest.mock('../request')を呼び出してJestに手動モックを使用するよう指示します。itは解決されるPromiseを返り値として期待します。最後にPromiseを返す限り、任意の数のPromiseをチェーンし、いつでもexpectを呼び出せます。

.resolves

解決されたPromiseの値をアンラップするより簡潔な方法として、resolvesを他のマッチャーと組み合わせて使用できます。Promiseが拒否されるとアサーションは失敗します。

it('works with resolves', () => {
expect.assertions(1);
return expect(user.getUserName(5)).resolves.toBe('Paul');
});

async/await

async/await構文を使用したテスト記述も可能です。先ほどの例を書き換えると以下のようになります:

// async/await can be used.
it('works with async/await', async () => {
expect.assertions(1);
const data = await user.getUserName(4);
expect(data).toBe('Mark');
});

// async/await can also be used with `.resolves`.
it('works with async/await and resolves', async () => {
expect.assertions(1);
await expect(user.getUserName(5)).resolves.toBe('Paul');
});

プロジェクトでasync/awaitを有効化するには、@babel/preset-envをインストールし、babel.config.jsで機能を有効にしてください。

エラーハンドリング

エラー処理には.catchメソッドを使用します。特定の数のアサーションが呼び出されることを検証するため、expect.assertionsの追加を忘れないでください。解決されたPromiseはテストを失敗させません:

// Testing for async errors using Promise.catch.
it('tests error with promises', () => {
expect.assertions(1);
return user.getUserName(2).catch(error =>
expect(error).toEqual({
error: 'User with 2 not found.',
}),
);
});

// Or using async/await.
it('tests error with async/await', async () => {
expect.assertions(1);
try {
await user.getUserName(1);
} catch (error) {
expect(error).toEqual({
error: 'User with 1 not found.',
});
}
});

.rejects

.rejectsヘルパーは.resolvesと同様に動作します。Promiseが解決されるとテストは自動的に失敗します。expect.assertions(number)は必須ではありませんが、テスト中に特定の数のアサーションが呼び出されることを保証するために推奨します。そうしないと.resolvesアサーションのreturn/awaitを忘れやすくなります。

// Testing for async errors using `.rejects`.
it('tests error with rejects', () => {
expect.assertions(1);
return expect(user.getUserName(3)).rejects.toEqual({
error: 'User with 3 not found.',
});
});

// Or using async/await with `.rejects`.
it('tests error with async/await and rejects', async () => {
expect.assertions(1);
await expect(user.getUserName(3)).rejects.toEqual({
error: 'User with 3 not found.',
});
});

このサンプルコードはexamples/asyncで参照できます。

setTimeoutのようなタイマーのテストについては、Timer mocksドキュメントをご覧ください。