👻
Jestで即時関数を含むコードをテストする
Jestで即時関数を含むソースファイルをテストする際に、そのままではエラーになってしまってテストできないものがありました。
前提条件
- Jest
- TypeScript
テスト対象のコード
テスト対象のコードは、テスト対象のコードと即時関数が同じファイルに書かれています。
sample.ts
// テスト対象のコード
// 即時関数(テスト対象ではない)
(() => {
const button = document.getElementById('button');
button.classList.add('active');
})();
// テストしたい関数
export function sampleTest(): string {
return 'Hello, World!';
}
テストコード
エラーになるケース
テストコードではJestを用いて関数の返り値をテストします。
sample.test.ts
import { sampleTest } from 'path/to/sample';
describe('sample', () => {
it('sample', () => {
const res = sampleTest();
expect(res).toBe('Hello, World!');
});
});
上記のテストを実行すると、テスト対象の関数だけでなく即時関数も実行されてしまい、処理によってはエラーになってしまいます。
FAIL path/to/sample.test.ts
● Test suite failed to run
TypeError: Cannot read properties of null (reading 'classList')
1 | (() => {
2 | const button = document.getElementById('button');
> 3 | button.classList.add('active');
| ^
4 | })();
5 |
6 | export function sampleTest(): string {
at classList (path/to/sample.ts:3:10)
at Object.<anonymous> (path/to/sample.ts:4:2)
at Object.<anonymous> (path/to/sample.test.ts:7:1)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 3.93 s
Ran all test suites within paths "path/to/sample.test.ts".
解決方法
エラーを解決するには即時関数内で実行される処理をモックすればOKです。ただし、テストコード内での記述場所が大切で、import
文よりも前に書く必要があります。
sample.test.ts
// 即時関数内の処理をモック
jest.spyOn(document, 'getElementById').mockReturnValue({
classList: {
add: jest.fn(),
},
} as unknown as HTMLElement);
// モックよりも後にimportする必要がある
import { sampleTest } from 'path/to/sample';
describe('sample', () => {
it('sample', () => {
const res = sampleTest();
expect(res).toBe('Hello, World!');
});
});
まとめ
即時関数を含むソースファイルをJestでテストする場合の注意点を記載しました。テストコードでは、テスト対象のimport文よりも前に即時関数内の処理をモックする必要があります。
Discussion