12
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jestのautomockをimport/export記法で使う

Last updated at Posted at 2017-09-30

jestとは

facebookが作ったテストフレームワークです。
automockという特殊な機能を持っていて、すべてのモジュールがモック化された状態でロードされます。
今回は、automockの使い方を書いておきます。

automockを使ったテストの書き方

まずは、jest用のconfigファイルを用意します。
package.jsonか、適当なjsonファイルに記述することができます。
package.jsonに書く場合は以下のとおり。

package.json
{
  ...dependenciesとかなんかいろいろな設定
  "jest": {
    "automock": true
  }
}

package.jsonに記載する場合は特になにも指定しなくても勝手に読み込んでくれます。
適当な設定ファイルに書く場合は以下のとおり。

jest.config.json
{
  "automock": true
}

実行する際にはjest --config ./jest.config.jsonという感じでファイルを指定する必要があります。

automockの威力

automockをオンにすると、テストコードで読み込むモジュールはすべてモック化されています。
あと、ここではautomock以外の話はあんまり書きません。(__test__というフォルダにテストコードを置く、とか。)

module.js
export function add(x, y) {
  return x + y;
}
__test__/module.test.js
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を使う方法から。

__test__/module.test.js
jest.dontMock("../module");
const module = require("../module");

expect(module.add(2, 3)).toBe(5);

module.js内部で別のモジュールを利用している場合は、それもjest.dontMockしてあげればよいです。

__test__/module.test.js
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が必要になります)
そこで、以下のようなコードを書いてみるとどうなるでしょうか。

__test__/module.test.js
jest.dontMock("../module");
import { add } from "../module";

expect(add(2, 3)).toBe(5);

これは、ざっくり書くと、以下のように変換されるらしいのです。

trans/__test__/module.test.js
var add = require("../module").add;
jest.dontMock("../module");

expect...

要は、モジュールの読み込みよりもjest.dontMockが後に実行されてしまうため、手遅れなのです。

対策

以下のように記述することで、require記法を回避することができます。

__test__/module.test.js
import { add } from "../module";
jest.unmock("../module");

expect...

これで、module.js以外のモジュールはモック化された状態でテストすることができるようになりました。
あとは好きにテストを書きましょう。

12
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?