概要
- flux の store 部分のテストの書き方。
- jest を使う。
- 入力は Action。結果は Store の状態と Change Listener が呼ばれることを確認。
- localStorage のモック。
テスト対象
web/static/js/stores/AuthStore.js
をテストします。
以下の機能を持っています。
- LOG_IN アクションを受け取ると token を localStorage に保存し、Change Listener に通知する。
- LOG_OUT アクションを受け取ると token を localStorage から削除し、Change Listener に通知する。
環境設定
elixir / phoenix の勉強用に作成したサンプル (tag qiita-jest-flux-store)を使って説明します。
jest-cli
, react-addons-test-utils
をインストールします。(npm に jest というパッケージもありますが別のものです。)
npm install jest-cli --save-dev
npm install react-addons-test-utils --save-dev
React 用に package.json
に設定を書きます。
JSX / ES6 の変換、react 関連のモジュールのモック化の除外設定をしています。
"jest": {
"rootDir": "./web/static/js",
"scriptPreprocessor": "../../../node_modules/babel-jest",
"unmockedModulePathPatterns": [
"react",
"../../../node_modules/react",
"../../../node_modules/react-dom",
"../../../node_modules/react-addons-test-utils"
]
}
テスト作成
jest は __tests__
ディレクトリにあるテストを実行するので、__tests__
ディレクトリを作成します。
mkdir web/static/js/stores/__tests__
AuthStore-test.js
を作成し、モックの設定をします。
jest はデフォルトで全てのモジュールをモック化するので、基本的には モック化しないモジュール のみ設定します。
jest.mock('../../dispatcher/AppDispatcher');
jest.dontMock('../../constants/Constants');
jest.dontMock('../AuthStore');
AuthStore はテスト対象なので除外します。
Constatnts は入力用のアクションが定義されているため除外します。
AppDispatcher はモック化されるはずですが、なぜかモックにならなかったため、モックにするように設定しています。
jest の実行環境では localStorage がないため、localStorage のモックも作成します。
var mock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key];
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', { value: mock });
Store が AppDispatcher に登録したコールバックは、mock から取得します。
callback = AppDispatcher.register.mock.calls[0][0];
このコールバックに Action を送ることで、Store の dispatcher を実行できます。
var actionLogIn = {
type: ActionTypes.LOG_IN,
token: 'abc'
};
callback(actionLogIn);
store から Change Listener 通知を確認するため、リスナーを作成し登録します。テスト実行後はリスナーを削除します。
var calledOnChange = false;
let onChange = () => calledOnChange = true;
Store.addChangeListener(onChange);
callback(actionLogIn);
Store.removeChangeListener(onChange);
callOnChange
はリスナーが呼ばれたことを確認するためのフラグです。
結果を確認します。
expect(Store.isLoggedIn()).toBeTruthy(); // ログイン状態の確認
expect(Store.getToken()).toBe('abc'); // トークンの確認
expect(calledOnChange).toBeTruthy(); // Change Listener が呼ばれたことの確認
ログアウトや初期値のテストを含めたテスト全体はこちらを参照してください。