jestとは
facebookが作ったテストフレームワークです。
automockという特殊な機能を持っていて、すべてのモジュールがモック化された状態でロードされます。
今回は、automockの使い方を書いておきます。
automockを使ったテストの書き方
まずは、jest用のconfigファイルを用意します。
package.jsonか、適当なjsonファイルに記述することができます。
package.jsonに書く場合は以下のとおり。
{
...dependenciesとかなんかいろいろな設定
"jest": {
"automock": true
}
}
package.jsonに記載する場合は特になにも指定しなくても勝手に読み込んでくれます。
適当な設定ファイルに書く場合は以下のとおり。
{
"automock": true
}
実行する際にはjest --config ./jest.config.jsonという感じでファイルを指定する必要があります。
automockの威力
automockをオンにすると、テストコードで読み込むモジュールはすべてモック化されています。
あと、ここではautomock以外の話はあんまり書きません。(__test__というフォルダにテストコードを置く、とか。)
export function add(x, y) {
return x + y;
}
import { add } from "../module";
describe("module", () => {
describe("#add", () => {
it("足し算した結果を返すこと。", () => {
expect(add(2, 3)).toBe(5);
})
});
});
さて上記のようなコードがあった時、関数addのテストが行われると思ったでしょう。
ところがどっこい、addはundefinedを返すので、テストはエラーになってしまいます。
理由は、automockはすべてのモジュールをモック化するからです。
正確には、addという関数は、jest.fn()で生成されるモック関数となっており、どんな呼び出しをしてもundefinedを返すようになってしまっています。
automockの状態でテストをする方法
以下のような記述でテストができます。
モジュールのロードの方法によってテストの仕方が異なりますので、注意してください。
requireをつかう
まずはrequireを使う方法から。
jest.dontMock("../module");
const module = require("../module");
expect(module.add(2, 3)).toBe(5);
module.js内部で別のモジュールを利用している場合は、それもjest.dontMockしてあげればよいです。
jest.dontMock("../module");
jest.dontMock("../dependentModule");
const module = require("../module");
expect(module.pow(2, 3)).toBe(8);
import/export
import/exportの問題点
こちらが本題です。
jestでは、テストコード、モジュールの実行時にはbabelによるコードのトランスパイルが行われ、それを元にテストが実行されます。
(したがって、.babelrcの設定が使用されますし、importを利用したい場合はbabel-preset-es2017が必要になります)
そこで、以下のようなコードを書いてみるとどうなるでしょうか。
jest.dontMock("../module");
import { add } from "../module";
expect(add(2, 3)).toBe(5);
これは、ざっくり書くと、以下のように変換されるらしいのです。
var add = require("../module").add;
jest.dontMock("../module");
expect...
要は、モジュールの読み込みよりもjest.dontMockが後に実行されてしまうため、手遅れなのです。
対策
以下のように記述することで、require記法を回避することができます。
import { add } from "../module";
jest.unmock("../module");
expect...
これで、module.js以外のモジュールはモック化された状態でテストすることができるようになりました。
あとは好きにテストを書きましょう。