Jestでno-moduleJSをテストする
IIFEとかUMDは厳しそう
関連記事
Jestで簡単ユニットテスト
JestをES6化してimport/exportを使う方法
------------------- ↓ 前書きはここから ↓-------------------
Jestでユニットテストを実践するようになって、
いろいろ不便な点がでている。
一番困るのがデータベース周りで、
どれを使っても煩雑になってしまう感じだ。
(フルスタックフレームワークなど無かった)
そしてもう一つ大きく困る点が、
昔ながらのJSファイルをテストできないことだ
昔ながらのJSファイルとは、
ロードするだけで動いてしまうタイプのコードだ。
(英語でもno-moduleとかwithout moduleとか名前がない)
ES6(export/import)登場以降は徐々に減っているが、
残っているところには残っている。
今回はそんなファイルをテストする方法を模索する
鍵となるソリューションは**VM Module**だ
ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪
------------------- ↓ 本題はここから ↓-------------------
JEST実行環境
こちらを参照
JestをES6化してimport/exportを使う方法
テスト開始
失敗する例
以下のようなプログラムがあったとする、。
const sum = function (a, b) {
return a + b;
}
var abc = 'def'
これをJestにかけるにも呼び出し方法がない。
試しにimportを使ってみると
describe('iife01.test.js',() => {
test('find sum', async () => {
const modules = await import('iife01')
console.log(sum)
})
})
結果
ReferenceError: sum is not defined
9 | test('abc', async () => {
10 | const modules = await import('iife01')
> 11 | console.log(sum)
| ^
(・ω・) ですよねー
sum
が定義されていないと言われてしまう
VM Moduleを使う場合
node本体にサンドボックス機能がついている
外部に影響の内容にjavascriptを実行する仕組み
javascriptファイルをテキストファイルとして取り出し、
evalやFunctionにかける方法もなくはないが、
テスト実行環境に反映されたり悪影響も多いので、
nodeのサンドボックス環境内で実行するようにする。
import fs from "fs";
import {Script, createContext} from "vm";
describe('iife02.test.js',() => {
test('find sum', async () => {
const code = fs.readFileSync('iife01.cjs');
const script = new Script(code.toString());
const context = {};
createContext(context);
script.runInContext(context);
console.log(context)
})
})
実行してみると
npm run test
console.log
{ sum: [Function: sum], abc: 'def' }
contextに定義されている sum
や abc
が取り出せているのがわかる
rewireモジュールを使う場合
調べているとrewireというモジュールを見つけた。
内容的には上記サンドボックスと同様のようで、
整備は楽かもしれない。
npm i -D rewire
また、babel-plugin-rewireというのもあって、
babel使ってるユーザーにはいいかもしれない。
import rewire from "rewire";
describe('iife02.test.js',() => {
test('find sum', async () => {
const modules = rewire(file)
console.log(modules.__get__('sum'), modules.__get__('abc'))
})
})
実行してみると
npm run test
console.log
[Function: sum] def
(・o・) おー
サンドボックスと同じ結果がでている
vm2モジュールを使う場合
上記サンドボックスと拡張したvm2というモジュールがある
(名前もうちょっとどうにかしてせいよ)
内容は正直深掘りしていないのでインストール方法だけ載せておく
npm i -D vm2
------------------- ↓ 後書はここから ↓-------------------
rewireの使い勝手がいいので、
一見するとこちらを使いそうだが、
昔のコードにありがちな DOM操作べた書き は対応できない
なので、基本的にはサンドボックス、あるいはvm2で良いかなと思う
DOMテストについては別途記事にする。。。やも。
IIFEやUMDをテストすることはできない
IIFEとは即時実行関数というが、
以下のようなコードを見たことがあるかもしれない。
(function (param) {
var abc = param
})(param)
ベタに書くと名前空間が大変なことになるので、
クロージャーの中にコードを書き、
クロージャーはロードとともに即実行するという記述方法。
ESM普及まではむしろ主流だった
UMDはそれを拡張したもので、
typescriptやbabelのコンパイル結果でよく見かけるものだ。
ただ、残念ながらこれはコードを書き換える以外にテストする方法がない。
Discussion