最初のテストを書く
このガイドでは、@cloudflare/vitest-pool-workersパッケージのインストールと設定方法を説明します。これにより、Vitestを使用してWorkersに対するテストを書く準備が整います。@cloudflare/vitest-pool-workersパッケージは、Vitestが通常Node.jsワーカースレッド ↗内で実行するコードをCloudflare Worker内で実行することによって機能します。@cloudflare/vitest-pool-workersを使用したテストの例については、レシピを参照してください。
-
Workerのルートディレクトリを開くか、新しいWorkerを作成します。
-
WorkerがESモジュール形式で開発されていることを確認してください。サービスワーカー形式からESモジュール形式に移行するには、ESモジュール形式への移行ガイドを参照してください。
-
プロジェクトの
wrangler.toml設定ファイルで、2022-10-31以上の互換性日を定義し、互換性フラグにnodejs_compatを含めます。
ターミナルウィンドウを開き、プロジェクトのルートディレクトリにいることを確認します。確認ができたら、次のコマンドを実行します:
npm install vitest@1.5.0 --save-dev --save-exactnpm install @cloudflare/vitest-pool-workers --save-dev上記のコマンドは、パッケージをpackage.jsonファイルに追加し、dev依存関係としてインストールします。
vitest.config.jsまたはvitest.config.tsファイルがまだない場合は、作成し、次の設定を定義する必要があります。
wrangler.tomlファイルを参照して、そのmainエントリポイント、互換性設定、およびバインディングを活用できます。
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({ test: { poolOptions: { workers: { wrangler: { configPath: "./wrangler.toml" }, }, }, },});内部的に、Workers Vitest統合はMiniflare ↗を使用しており、これはwrangler devのローカルモードを支える同じシミュレーターです。高度な設定のために、オプションをMiniflareに直接渡すことができます。
たとえば、テストで使用されるバインディングを追加するには、defineWorkersConfigにminiflareを追加できます:
export default defineWorkersConfig({ test: { poolOptions: { workers: { main: "./src/index.ts", miniflare: { kvNamespaces: ["TEST_NAMESPACE"], }, }, }, },});この設定は、テストでのみアクセス可能なKV名前空間TEST_NAMESPACEを追加します。この方法を使用すると、Durable Objectsやサービスバインディングなどの既存のバインディングを追加または上書きできます。
TypeScriptを使用している場合は、Cloudflare Workersおよびcloudflare:testの型を定義して、適切に検出されるようにする必要があります。テストと同じフォルダー(つまりtest)にtsconfig.jsonを追加し、次の内容を追加します:
{ "extends": "../tsconfig.json", "compilerOptions": { "moduleResolution": "bundler", "types": [ "@cloudflare/workers-types/experimental", "@cloudflare/vitest-pool-workers" ] }, "include": ["./**/*.ts", "../src/env.d.ts"]}このファイルを保存すれば、最初のテストを書く準備が整いました。
上記のガイドに従って基本的なWorkerを作成した場合、srcフォルダーに次のfetchハンドラーがあるはずです:
export default { async fetch(request, env, ctx) { return new Response("Hello World!"); },};export default { async fetch(request, env, ctx): Promise<Response> { return new Response("Hello World!"); },} satisfies ExportedHandler<Env>;このWorkerはリクエストを受け取り、"Hello World!"のレスポンスを返します。これをテストするために、次のテストファイルを持つtestフォルダーを作成します:
import { env, createExecutionContext, waitOnExecutionContext,} from "cloudflare:test";import { describe, it, expect } from "vitest";// 他のソースファイル/関数をここでインポートすることもできますimport worker from "../src";
describe("Hello World worker", () => { it("responds with Hello World!", async () => { const request = new Request("http://example.com"); // `worker.fetch()`に渡すための空のコンテキストを作成 const ctx = createExecutionContext(); const response = await worker.fetch(request, env, ctx); // テストアサーションを実行する前に、`ctx.waitUntil()`に渡されたすべての`Promise`が解決されるのを待つ await waitOnExecutionContext(ctx); expect(await response.text()).toBe("Hello World!"); });});import { env, createExecutionContext, waitOnExecutionContext,} from "cloudflare:test";import { describe, it, expect } from "vitest";// 他のソースファイル/関数をここでインポートすることもできますimport worker from "../src";
// 現在、`worker.fetch()`に渡すために正しく型付けされた`Request`を取得するには、次のようにする必要があります。const IncomingRequest = Request<unknown, IncomingRequestCfProperties>;
describe("Hello World worker", () => { it("responds with Hello World!", async () => { const request = new IncomingRequest("http://example.com"); // `worker.fetch()`に渡すための空のコンテキストを作成 const ctx = createExecutionContext(); const response = await worker.fetch(request, env, ctx); // テストアサーションを実行する前に、`ctx.waitUntil()`に渡されたすべての`Promise`が解決されるのを待つ await waitOnExecutionContext(ctx); expect(await response.text()).toBe("Hello World!"); });});Workerに404パスを処理する機能を追加します。この機能は、テキストNot foundとステータスコード404を返します。
export default { async fetch(request, env, ctx) { const { pathname } = new URL(request.url);
if (pathname === "/404") { return new Response("Not found", { status: 404 }); }
return new Response("Hello World!"); },};export default { async fetch(request, env, ctx): Promise<Response> { const { pathname } = new URL(request.url);
if (pathname === "/404") { return new Response("Not found", { status: 404 }); }
return new Response("Hello World!"); },} satisfies ExportedHandler<Env>;これをテストするために、テストファイルに次の内容を追加します:
it("responds with not found and proper status for /404", async () => { const request = new Request("http://example.com/404"); // `worker.fetch()`に渡すための空のコンテキストを作成 const ctx = createExecutionContext(); const response = await worker.fetch(request, env, ctx); // テストアサーションを実行する前に、`ctx.waitUntil()`に渡されたすべての`Promise`が解決されるのを待つ await waitOnExecutionContext(ctx); expect(await response.status).toBe(404); expect(await response.text()).toBe("Not found");});it("responds with not found and proper status for /404", async () => { const request = new IncomingRequest("http://example.com/404"); // `worker.fetch()`に渡すための空のコンテキストを作成 const ctx = createExecutionContext(); const response = await worker.fetch(request, env, ctx); // テストアサーションを実行する前に、`ctx.waitUntil()`に渡されたすべての`Promise`が解決されるのを待つ await waitOnExecutionContext(ctx); expect(await response.status).toBe(404); expect(await response.text()).toBe("Not found");});@cloudflare/vitest-pool-workersGitHubリポジトリ ↗ -@cloudflare/vitest-pool-workersパッケージを使用したテストの例。