Jest
基本のき
インストール
code:shell
npm install -D jest
yarn add -D jest
設定など
TypeScript を利用する場合は ts-jest をインストール
Matcher
code:javascript
// === で厳密な等価性をテストする
expect(2 + 2).toBe(4);
// オブジェクト, 配列の全てのフィールドを再帰的にチェックする
expect({one: 1}).toEqual({one: 1, two: 2});
テストのグルーピングについて
実行対象のテストをグルーピングする方法はこれ!というものが公式から提供されてはいないので、パターンマッチ機能を使おうという意見が多いようだ。例えば、ファイル名でマッチングする。
その他にも、テスト文言でマッチングする方法もあるようだ。
個人的にはファイル名の方が、中身を書く時にいちいち命名にそう必要がなくて楽そうだ。
モック
モック関数 でできること。
機能の実装を省略する
関数の呼び出しをキャプチャする
new メソッドで初期化されるコンストラクタ関数のインスタンスをキャプチャする
テスト時に戻り値を設定する
手動モック と 自動モック がある。
モック関数
Jest のテストでは、様々な方法で モック関数を作成できる。モック関数の状態はテスト中記録されるため、テストの終了後のモック関数の状態を調べることで、モック関数が何回呼び出されたか?どのような引数を取ったか?などを検証することができる。 戻り値
テスト用の値を注入することもできる。
code:js
const myMock = jest.fn();
console.log(myMock());
// > undefined
myMock
.mockReturnValueOnce(10)
.mockReturnValueOnce('x')
.mockReturnValue(true);
console.log(myMock(), myMock(), myMock(), myMock());
// > 10, 'x', true, true
状態の検証
モックオブジェクト状態は、.mock プロパティに記録されている。.mock プロパティには、モック関数呼び出し時のデータや関数の返り値が記録されている。関数呼び出し時の this の値も格納されている。
code:javascript
// function はちょうど 1 回だけ呼ばれた
expect(someMockFunction.mock.calls.length).toBe(1);
// 関数の 1 回目の呼び出しの 1 番目の引数は 'first arg' だった
expect(someMockFunction.mock.calls00).toBe('first arg'); // 関数の 1 回目の呼び出しの 2 番目の引数は 'second arg' だった
expect(someMockFunction.mock.calls01).toBe('second arg'); // 関数の 1 回目の呼び出しの返り値は 'return alue' だった
expect(someMockFunction.mock.results0.value).toBe('return value'); // この関数はちょうど 2 回インスタンス化された
expect(someMockFunction.mock.instances.length).toBe(2);
// この関数の 1 回目のインスタンス化で返されたインスタンスは、
// name プロパティを持っており、その値は 'test' であった
expect(someMockFunction.mock.instances0.name).toEqual('test'); モック関数の作成: jest.fn
最も単純なモックオブジェクトの生成方法は、jest.fn(implementation) を利用してモックオブジェクトを作成することである。
code:javascript
// 何も与えない場合
const mockFn = jest.fn();
mockFn();
// 呼び出されたかどうか?を確認できる
expect(mockFn).toHaveBeenCalled();
// 実装を与える場合
const returnsTrue = jest.fn(() => true);
console.log(returnsTrue()); // true;
スパイ: jest.spyOn
jest.spyOn(object, methodName) は、jest.fn と同様にモック関数を返す。jest.fn は実装を丸ごと渡す必要があるが、これは引数に指定したメソッドも実装してくれる。
code:javascript
const video = {
play() {
return true;
},
};
module.exports = video;
code:javascript
const video = require('./video');
test('plays video', () => {
const spy = jest.spyOn(video, 'play');
const isPlaying = video.play();
expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(true);
spy.mockRestore();
});
外部モジュールのモック: jest.mock
jest.mock(...) を利用すると、外部モジュールをモックすることができる。
code:users.js
import axios from 'axios';
class Users {
static all() {
return axios.get('/users.json').then(resp => resp.data);
}
}
export default Users;
code:users.test.js
import axios from 'axios';
import Users from './users';
jest.mock('axios');
test('should fetch users', () => {
const resp = {data: users};
// 偽のレスポンスを返す
axios.get.mockResolvedValue(resp);
// or you could use the following depending on your use case:
// axios.get.mockImplementation(() => Promise.resolve(resp))
return Users.all().then(resp => expect(resp.data).toEqual(users));
});
code:users.test.js
jest.mock('../foo');
// モックの実装を加える
// 複数回の呼び出しで異なる挙動を与えたい場合は mockImplementationOnce を利用する
const foo = require('../foo');
foo.mockImplementation(() => 42);
foo();
// > 42
TypeScript とモック