[小ネタ] Jest の beforeEach は test と it ごとに走る

JavaScript

はじめに

こんぬづは、以前少し触れたPUBGというゲームを、社内で一緒にやってくれる仲間を見つけてほくほくしている田中です。クラスメソッドSteam部、楽しいよ!

さて、本題です。

私はこれまでiOSの開発を行ってきて、テストフレームワークはQuickというものを使っていました。このフレームワークは、ネストの中の同じ階層にある describe ごとに beforeEach が実行されるという仕様でした。それに対してFacebook製のテストフレームワークである Jest は test と it ごとに beforeEach が実行されるという仕様で、違いがあります。

解説

例えば先述した勘違いが問題になるのはこんなとき。

describe('ユーザー認証', () => {
  let mockObj = { 'id' : '123' };

  beforeEach(() => {
    // 初期化処理
    mockObj = { 'id' : '123' };
  });

  describe('正規ユーザーのとき', () => {
    // この時のmockObjは { 'id' : '123' }
    Object.assign(mockObj, { 'name' : 'tanaka' });
    // assignしたのでmockObjは { 'id' : '123', 'name' : 'tanaka' } になっている

    it('response.nameがtanakaであること', () => {
      // この時のmockObjは、直前でbeforeEachが走り初期化されているので、 { 'id' : '123' } となっている。
      // (想定では { 'id' : '123', 'name' : 'tanaka' } になっていてほしい)
      apiClient.request((response) => {
          expect(response.name).toEqual(mockObj.name); // Error!!!
      });
    });
  });
});

// Expected value to equal:
//       undefined
//     Received:
//       "tanaka"

まとめ

BDDで書けるテストフレームワームはどれも同じような仕様で、書き方も同じだろうとたかをくくって痛い目を見ました。根拠のない過信、ダメ、絶対。計らずもテストフレームワークごとに違いがあるということを発見しましたが、言語やツールごとに違いがあるのは楽しいですね。

参考・関連

AWS Cloud Roadshow 2017 福岡