Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

テストの作成

最終更新 Markdown で表示Agent セットアップ

このガイドでは、Miniflare を設定して Worker をテストする方法を説明します。Miniflare は低レベル API で、Worker の実行とテスト方法を細かく制御できます。

Miniflare を使うには、Miniflare v3 の最新版をインストールしてください。

npm i -D miniflare@latest

以降の説明では node:test テストフレームワークを使いますが、任意のテストフレームワークを使えます。

Miniflare は低レベル API で、Worker 実行用の設定オプションが多数あります。テストで使うのは一部だけで十分な場合がほとんどです。Miniflare でできることの全体は API リファレンス を参照してください。

テストを書く前に、Worker を作成します。Miniflare は Cloudflare プラットフォームのプリミティブをエミュレートする低レベル API です。Worker は JavaScript で書くか、テスト環境に 独自のビルドパイプライン を組み込む必要があります。JavaScript のみの Worker の例は次のとおりです。

src/index.jsjs
export default {
	async fetch(request) {
		return new Response(`Hello World`);
	},
};

次に、最初のテストファイルを作成します。

src/index.test.jsjs
import assert from "node:assert";
import test, { after, before, describe } from "node:test";
import { Miniflare } from "miniflare";

describe("worker", () => {
	/**
	 * @type {Miniflare}
	 */
	let worker;

	before(async () => {
		worker = new Miniflare({
			modules: [
				{
					type: "ESModule",
					path: "src/index.js",
				},
			],
		});
		await worker.ready;
	});

	test("hello world", async () => {
		assert.strictEqual(
			await (await worker.dispatchFetch("http://example.com")).text(),
			"Hello World",
		);
	});

	after(async () => {
		await worker.dispose();
	});
});

上のテストは node --test で実行できます。

テストファイルのハイライト行は、JavaScript Worker を Miniflare で動かす設定です。Miniflare の準備ができたら、各テストは実行中の Worker へリクエストを送り、レスポンスを検証できます。これが Vitest 連携 と比べたときの、Miniflare で Worker をテストする主な制約です。Worker へのアクセスはすべて Miniflare の dispatchFetch() API 経由になり、Worker 内の個別関数を単体テストできません。

テストはどのランタイムで動きますか?

Vitest 連携 を使う場合、テストスイート全体が workerd 上で動きます。そのため、個別関数の単体テストが可能です。 一方、別のテストフレームワークで Miniflare 経由でテストする場合、workerd 上で動くのは Worker 自体だけです。テストファイルは Node.js で動きます。そのため、Worker から関数をテストファイルへインポートすると、その関数が workerd 固有の挙動に依存している場合、実行時と異なる動きをすることがあります。

バインディングの操作

Miniflare の dispatchFetch() API では、Worker へリクエストを送り、正しいレスポンスが返ることを検証できます。一方、テストからバインディングを直接操作したい場合もあります。そのような用途には、Miniflare の getBindings() API があります。たとえば、テストで環境変数にアクセスするには、テストファイル src/index.test.js を次のように変更します。

src/index.test.jsdiff
...
describe("worker", () => {
	...
	before(async () => {
		worker = new Miniflare({
			...
+			bindings: {
+				FOO: "Hello Bindings",
+			},
		});
		...
	});

	test("text binding", async () => {
		const bindings = await worker.getBindings();
		assert.strictEqual(bindings.FOO, "Hello Bindings");
	});
	...
});

KV や R2 などのローカルリソースも、Worker から使うのと同じ API で操作できます。KV 名前空間を操作する例は次のとおりです。

src/index.test.jsdiff
...
describe("worker", () => {
	...
	before(async () => {
		worker = new Miniflare({
			...
+			kvNamespaces: ["KV"],
		});
		...
	});

	test("kv binding", async () => {
		const bindings = await worker.getBindings();
		await bindings.KV.put("key", "value");
		assert.strictEqual(await bindings.KV.get("key"), "value");
	});
	...
});

より複雑な Worker

上の例は、単一の JavaScript ファイルからなる簡単な Worker のテスト方法です。実際の Worker は、それより複雑なことがほとんどです。Miniflare は、Worker を構成するすべてのファイルを API で直接渡せます。

new Miniflare({
	modules: [
		{
			type: "ESModule",
			path: "src/index.js",
		},
		{
			type: "ESModule",
			path: "src/imported.js",
		},
	],
});

Worker が大きくなると、これは煩雑になります。そこで Miniflare は、モジュールグラフをたどって含めるモジュールを自動特定することもできます。

new Miniflare({
	scriptPath: "src/index-with-imports.js",
	modules: true,
	modulesRules: [{ type: "ESModule", include: ["**/*.js"] }],
});

カスタムビルド

実際のケースでは、Worker をプレーンな JavaScript で書くことは少なく、npm パッケージなどの依存をインポートする複数の TypeScript ファイルからなり、ビルドツールでバンドルします。Miniflare で直接テストする場合は、テストの前にこのビルドツールを実行する必要があります。実行方法は使うテストフレームワークによりますが、node:test では setup() フックが一般的です。たとえば Wrangler で Worker をビルドおよびデプロイしている場合は、次のように wrangler build コマンドを spawn できます。

before(() => {
	spawnSync("npx wrangler build -c wrangler-build.json", {
		shell: true,
		stdio: "pipe",
	});
});

役に立ちましたか?