TypeScript(NodeJS)

【TypeScript】UnitTestでexportされていない別モジュールのfuncitonをテストする

ユニットテスト、書いてあると安心感がありますよね。
(いや、書いてないと怒られる時代に突入してるか)

しかしユニットテストって言語によって書き方の作法が違うし、テストフレームワークも複数あったりと・・・。

慣れるまでは、テスト対象のコードを実装するよりもテストコードを書く方が大変だったりします。
(テストパターンの数の問題ではなく)

また言語によっては、private なメソッドや関数のテストが面倒だったり。

今回は TypeScript で export されていない外部ファイルの function のテストの方法について紹介します。

TypeScriptのテストフレームワーク

ユニットテストを実装する際、どのようなライブラリを使うのがベターなのか。

その時代によってトレンドは様々でしょうが、やはり使い慣れたものがあった方がいいですよね。

Java や Kotlin だと、SpringBootTest や KotlinTest を使う機会が多いでしょうか。

じゃあ TypeScript は?っというと、どうやら Jest が人気のようですね。

シンプルにテストが書けて、モックの定義もしやすいとベストなのですが果たして・・・。

関数のテストコード(function)

function のテストは簡単。

test() の引数に関数名とテスト実装を定義するだけです。

では、シンプルなテストを実装してみます。

hoge.ts に定義されている getHogeType() の function をターゲットとしましょう。

hoge.ts を t、テストケースのターゲットを tt とするのが一般的なのでしょうか。

クラスのテストコード(class)

クラスの場合は、describe() にクラス名を定義して、その中にメソッドのテストコードを書いていきます。

以下は Hoge クラスのコンストラクタと getHoge メソッドのテスト例です。

privateのメソッドのモック化

残念ながら private な関数やメソッドのテストには素直にはいきません。

ただし、class 内の private なメソッドのモック化は簡単。

クラスのインスタンスを作成したら、[ ] の括弧でメソッド名を指定すれば、中身を書き換えることができるのです。

const hoge = new t.Hoge();
hoge[“_fuga”] = () => { return “fuga”; }

privateの関数の参照

では class 外の export されていない関数はどうすればいいか。

Java や Kotlin の時にリフレクションを使ったのと同じような状況ですね。

TypeScript の場合は rewire というライブラリを使うのが良さそう。

開発時しか使わないので、–save-dev でいいでしょう。

$ npm install –save-dev rewire @types/rewire

これでインポートしたモジュールの関数が参照できると思ったら・・・

どうやら ts ファイルではなく、ビルドして生成された js ファイルを指定しないといけないのですね。

ここで大きくハマりました。

最初は ts ファイルを指定したり、拡張子を付けたり外したりと試していましたが、下記のエラーは変わらず。

まさか生成された JS ファイルの方を指定するとは思ってもなく・・・。

この手の問題で時間を潰すのはもったいないですが、これも勉強ですね。

まとめ

TypeScript で export していない外部ファイルの function のテストをする方法を紹介してきました。

最初に調べていた時は、「package.json に以下を定義しろ」という記事ばかりヒットして謎だったのですよね。

{“type”: “module”}

まだまだ TypeScript や NodeJS 関連の検索には慣れていないので、もう少し理解を深めていきたいところです。