[JavaScript] JasmineからJestへの移行


4年ほど前に作ったAWS Lambdaプロジェクトがありました。
もろもろ更新しようとAWS SAMでプロジェクトを作り直したところ、テストライブラリとして Jest が入っていました。

移行する必要があるのか?
と言われると、ないですけれど、
趣味なのでやってみます。

テストファイルの場所を移動する

テスト対象ファイルとテストファイルを同一ディレクトリに置いていました。

src/lib/myclass.js
src/lib/myclass.spec.js

Jestは賢いからか、このままでもきちんとテストを見つけて実行してくれます。

ただここは、AWS SAMの流儀に従って場所を分けました。

src/lib/myclass.js
__tests__/lib/myclass.spec.js

require を書き換え

テストファイルの場所を移動したので、requireを書き換えました。

Before
const myclass = require('./myclass')
After
const myclass = require('../../src/lib/myclass.js');

ファイル名を変更……する?

テストファイルには *.spec.js という拡張子をつけていました。

*.test.js のほうが、流儀っぽいです。

ここは、面倒なのでそのままにしておきます。

モックの書き換え

Jasmineのスパイを、Jestのモックへ書き換えます。

モックの作成

作成部分はこうなりました。

Before
const dbx = jasmine.createSpyObj('Dropbox', [
    'filesListFolder',
    'filesListFolderContinue',
    'filesGetTemporaryLink'
]);
After
const dbx = {
    filesListFolder:jest.fn(),
    filesListFolderContinue:jest.fn(),
    filesGetTemporaryLink:jest.fn()
};

戻り値の設定

Jasmineはand.returnValue()で戻り値を設定していました。

Before
dbx.filesListFolder.and.returnValue(
    new Promise(resolv => {
        resolv({ entries: [], has_more: false });
    })
);

JestはmockReturnValueOnce()を使うようです。

After
dbx.filesListFolder.mockReturnValueOnce(
    new Promise(resolv => {
        resolv({ entries: [], has_more: false });
    })
);

複数回呼び出されたときの戻り値の設定

Jasmineは戻り値を複数個並べていました。

Before
dbx.filesListFolderContinue.and.returnValue(
    new Promise(resolv => {
        resolv({ entries: [], has_more: true, cursor: dummyCursor2 });
    }),
    new Promise(resolv => {
        resolv({ entries: [], has_more: false });
    })
);

JestはmockReturnValueOnceを必要回数呼び出せばよいようです。

After
dbx.filesListFolderContinue.mockReturnValueOnce(
    new Promise(resolv => {
        resolv({ entries: [], has_more: true, cursor: dummyCursor2 });
    }));
dbx.filesListFolderContinue.mockReturnValueOnce(
    new Promise(resolv => {
        resolv({ entries: [], has_more: false });
    })
);

非同期関数のテスト

async関数の戻り値はexpectAsync()で待ち受けて、toBeResolvedToでテストしていました。

Before
await expectAsync(actual).toBeResolvedTo('http://hoge.example.com/');

Jestはexpect()にして、resolvesプロパティの値をテストすればよいようです。

After
await expect(actual).resolves.toBe('http://hoge.example.com/');

実は自動的に移行できたかも?

終わってみてから気づきました。

移行するためのコマンドがありました。

npx jest-codemods

これを使えば、何もすることなかったかも?