An Async Example
まず、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)); }); }); }
テストではネットワークに接続したくないため、 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.substr('/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).toEqual('Mark')); });
マニュアルモックを使用するようにjest.mock('../request')
を呼び出します。 it
は戻り値が解決されようとしているPromiseであることを期待します。 最後にPromiseを返す限り、任意の数だけPromiseをチェーンして任意のタイミングでexpect
を呼び出すことができます。
.resolves
#
Jest バージョン20.0.0+で利用可能 #
resolves
を使用することで、他のいかなるマッチャと共に成功したpromiseの値を取り出すための記述量を減らすことができます。promiseがrejectされた場合はアサーションは失敗します。
it('works with resolves', () => { expect.assertions(1); return expect(user.getUserName(5)).resolves.toEqual('Paul'); });
async
/await
#
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).toEqual('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.toEqual('Paul'); });
プロジェクトでasync
/await
を有効にするには、babel-preset-env
をインストールし、 .babelrc
ファイルで機能を有効化します。
エラー処理 #
エラーは .catch
メソッドで処理することができます。 想定した数のアサーションが呼ばれたことを確認するため、expect.assertions
を必ず追加して下さい。 さもなければpromiseがrejectされなかった場合にテストが失敗したと判定されません:
// Testing for async errors using Promise.catch. test('tests error with promises', async () => { expect.assertions(1); return user.getUserName(2).catch(e => expect(e).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 (e) { expect(e).toEqual({ error: 'User with 1 not found.', }); } });
.rejects
#
Jest バージョン20.0.0+で利用可能 #
.rejects
ヘルパーは .resolves
ヘルパーのような働きをします。promiseが成功した場合、テストは自動的に失敗します。
// 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ドキュメントを読んで下さい。