0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cloud Run functions × TypeScript 開発をしよう!【テスト:JestでTypeScriptの関数をテストする】

Last updated at Posted at 2024-12-11

はじめに

この記事では以下のことについて説明しています。

  • JestでTypeScirptの関数をテストする方法
  • Jest(ts-jest)のESM対応とモジュール解決方法

Jestの概要や書き方については説明しません。公式サイトを参考にしてください。


Jestは JavaScript のテスティングフレームワークです。TypeScriptのコードは Jest だけではテストできません。
以下のものが必要です。

  • Jest
  • ts-jest
  • @types/jest

ts-jest によって TypeScript で書いたテストコードを直接テスト実行することができます。@types/jest は Jest のAPIの型定義ファイルです。

今回紹介するケースは ESM対応とモジュールインポートを実施したテストです。

必要なライブラリのインストール

npm install --save-dev jest ts-jest @types/jest

jest.config.json の作成(TypeScript用)

npx ts-jest config:init

実行すると以下の jest.config.json が出力されます。

jest.config.json
/** @type {import('ts-jest').JestConfigWithTsJest} **/
export default {
  testEnvironment: "node",
  transform: {
    "^.+.tsx?$": ["ts-jest",{}],
  },
};

テストの作成 / 実施

今回は以下のケースで説明していきます。

ディレクトリ構成
.
├── src
│   ├── hoge
│   │   └── hoge.ts
│   └── index.ts
├── test
│   └── hoge.test.ts
├── package.json
├── jest.config.js
└── tsconfig.json

test ディレクトリのコードも TypeScript のコンパイル対象に含めたいので、 include にその設定を追記しましょう。

tsconfig.json
{
  "compilerOptions": {
    "target": "es2022",
    "module": "node16",
    "moduleResolution": "node16",
    "baseUrl": "./src",
    "paths": {
      "@/*": ["./*"]
    },
    "rootDirs": ["./src"],
    "outDir": "./dist",
    "sourceMap": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
  },
  "include": ["src/**/*", "test/**/*"], // "test/**/*" を追加する
  "exclude": ["dist", "node_modules"]
}

上記の ./src/hoge/hoge.ts のテストを書いてみます。

./src/hoge/hoge.ts
export const hoge: () => string = () => "hogehoge";
./test/hoge.test.ts
test("check", () => {
  console.log("OK");
});

以下のコマンドを pakcage.json に追加します。

package.json / testコマンド
  "scripts": {
    "test": "jest"
  },
test実行
$ npm run test

> advent-calendar-2024@1.0.0 test
> jest

  console.log
    OK

      at Object.<anonymous> (test/hoge.test.ts:2:13)

 PASS  test/hoge.test.ts
  ✓ check (14 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.62 s
Ran all test suites.

無事テストを実行することができました。

ESM対応をする

例えば以下のようなモジュールインポートを行うテストを書いたとしましょう。

test/hoge.test.ts
import { hoge } from '@/hoge/hoge';

test("check", () => {
    const hogehoge = hoge();
    expect(hogehoge).toBe("hogehoge");
});  

これで npm run test を実行するとテストは成功しますが、tsconfig.json"module": "node16" を指定しているためIDEのエラーチェックに引っかかります。
import { hoge } from '@/hoge/hoge' の部分で赤い波線と

Cannot find module '@/hoge/hoge' or its corresponding type declarations.ts(2307)

というエラーメッセージが表示されます。

スクリーンショット 2024-12-11 16.23.56.png

これは末尾に.jsと拡張子を指定すると消えます。が、実行すると以下のようなエラーが出ます。

失敗する
$ npm run test

> advent-calendar-2024@1.0.0 test
> jest

 FAIL  test/hoge.test.ts
  ● Test suite failed to run

    Configuration error:
    
    Could not locate module @/hoge/hoge.js mapped as:
    /Users/usr0302216/local/advent-calendar-2024/src/$1.
    
    Please check your configuration for these entries:
    {
      "moduleNameMapper": {
        "/^@\/(.*)$/": "/Users/xxx/local/advent-calendar-2024/src/$1"
      },
      "resolver": undefined
    }

    > 1 | import { hoge } from '@/hoge/hoge.js';
        | ^
      2 |
      3 | test("check", () => {
      4 |     const hogehoge = hoge();

      at createNoMappedModuleFoundError (node_modules/jest-resolve/build/resolver.js:759:17)
      at Object.<anonymous> (test/hoge.test.ts:1:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.094 s, estimated 2 s
Ran all test suites.

モジュールインポートに失敗しているようです。

ts-jest を使う上でESM対応の方法は

など様々な方法がありますが、1番目の「ESM対応プラグインの導入」を取ります。

プラグインのインストール

npm install --save-dev ts-jest-resolver

jest.config.jsonresolver: "ts-jest-resolver" を追加

jest.config.json / resolver
/** @type {import('ts-jest').JestConfigWithTsJest} **/
export default {
  testEnvironment: "node",
  transform: {
    "^.+.tsx?$": ["ts-jest",{}],
  },
  resolver: "ts-jest-resolver",
};

しかし、これでも実行すると依然としてモジュール解決できずエラーが発生します。

$ npm run test

> advent-calendar-2024@1.0.0 test
> jest

 FAIL  test/hoge.test.ts
  ● Test suite failed to run

    Cannot find module '@/hoge/hoge.js' from 'test/hoge.test.ts'

    > 1 | import { hoge } from '@/hoge/hoge.js';
        | ^
      2 |
      3 | test("check", () => {
      4 |     const hogehoge = hoge();

      at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:427:11)
      at Object.<anonymous> (test/hoge.test.ts:1:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.12 s, estimated 2 s
Ran all test suites.

実は Jest は何も設定していない状態で tsconfig.jsonpathsbashUrl の設定を読み込むことができません。jest.config.jsonmoduleNameMapper オプションにその設定を伝える必要があります。

jest.config.json に以下を追記しましょう。

jest.config.json / moduleNameMapper
/** @type {import('ts-jest').JestConfigWithTsJest} **/
export default {
  testEnvironment: "node",
  transform: {
    "^.+.tsx?$": ["ts-jest",{}],
  },
  moduleNameMapper: {
    "^@/(.*)$": '<rootDir>/src/$1',
  },
  resolver: "ts-jest-resolver",
};

これで実行してみましょう。

$ npm run test

> advent-calendar-2024@1.0.0 test
> jest

 PASS  test/hoge.test.ts
  ✓ check (2 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.058 s
Ran all test suites.

これで無事テストを通すことができました。


以上、Jestを使ってTypeScriptの関数をテストする方法を紹介しました。
次回はもう一回くらいテストのことについて書いてみようと思います。

おまけ

「言った通りにやったのに上手くいかないじゃん!!」という方もいらっしゃると思います。
一度テストディレクトリの名前を確認して見てください。 ディレクトリ名が間違っている可能性があります。tests(複数形)になっていますか? test(単数系)になっていますか?

僕はこれで2時間くらい溶かしました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?