Workers Vitest プラグインには、次の既知の問題があります。
V8 ↗ によるネイティブコードカバレッジはサポートされていません。Istanbul ↗ によるインストルメント済みコードカバレッジを使う必要があります。セットアップ手順は Vitest Coverage ドキュメント ↗ を参照してください。
Vitest の フェイクタイマー ↗ は、KV、R2、キャッシュシミュレーターには適用されません。たとえば、フェイク時刻を進めて KV キーを期限切れにはできません。
exports.default.fetch() で結合テストを書くときの export default { ... } ハンドラー内、または Durable Object のイベントハンドラー内では、動的 import() 文は動きません。ハンドラーを直接 import して呼ぶか、グローバルスコープで静的 import 文を使ってください。
Durable Objects での WebSockets は、ファイル単位のストレージ分離ではサポートされません。回避策として、--max-workers=1 --no-isolate で共有ストレージを使ってテストを実行します。
ストレージ分離はテストファイル単位です。テストランナーは、各テストファイルの終了時にストレージへの書き込みを元に戻します。詳細は 分離と並行性のドキュメント を参照してください。よくある問題を避けるため、Cloudflare は次を推奨します。
ストレージサービスへ読み書きするすべての Promise を、必ず await してください。
// Example: Seed data
beforeAll(async () => {
await env.KV.put("message", "test message");
await env.R2.put("file", "hello-world");
});Service Worker または Durable Object の RPC メソッドを呼び、プリミティブ以外の値(オブジェクトや RpcTarget を拡張するクラスなど)を返す場合は、using キーワードでリソースを破棄できるタイミングを明示してください。このテスト例 ↗ と、詳細は explicit-resource-management を参照してください。
using result = await stub.getCounter();fetch または R2.get() でリクエストするときは、内容をアサートしない場合でも、レスポンス本文全体を消費してください。例:
test("check if file exists", async () => {
await env.R2.put("file", "hello-world");
const response = await env.R2.get("file");
expect(response).not.toBe(null);
// Consume the response body even if you are not asserting it
await response.text();
});ctx.exports プロパティは、メイン Worker のエクスポートへアクセスします。Workers Vitest 連携は、esbuild で Worker ソースコードを静的解析し、これらのエクスポートを自動推定しようとします。ただし、仮想モジュールや、esbuild がたどれないワイルドカード再エクスポートなど、複雑なビルド構成では、ctx.exports オブジェクトのプロパティが欠けることがあります。
たとえば、ワイルドカードエクスポートで仮想モジュールからエントリポイントを再エクスポートする Worker を考えます。
// index.ts
export * from "@virtual-module";この場合、@virtual-module からのエクスポート(MyEntrypoint など)は自動推定できず、ctx.exports から欠けます。
回避策として、Vitest 設定に additionalExports オプションを追加します。
import { cloudflareTest } from "@cloudflare/vitest-plugin";
import { defineConfig } from "vitest/config";
export default defineConfig({
plugins: [
cloudflareTest({
wrangler: { configPath: "./wrangler.jsonc" },
additionalExports: {
MyEntrypoint: "WorkerEntrypoint",
},
}),
],
});additionalExports オプションは、キーがエクスポート名、値がエクスポートの種類("WorkerEntrypoint"、"DurableObject"、"WorkflowEntrypoint")のマップです。
Error: Cannot use require() to import an ES Module や Error: No such module などのモジュール解決の問題が起きた場合は、deps.optimizer ↗ オプションでこれらの依存関係をバンドルできます。
import { cloudflareTest } from "@cloudflare/vitest-plugin";
import { defineConfig } from "vitest/config";
export default defineConfig({
plugins: [
cloudflareTest({
// ...
}),
],
test: {
deps: {
optimizer: {
ssr: {
enabled: true,
include: ["your-package-name"],
},
},
},
},
});例は Recipes ページにあります。
Vitest は workerd ↗ ランタイム向けにパッケージを解決するよう設定されていますが、グローバルセットアップファイルは Node.js 環境で実行します。そのため、Postgres.js ↗ のように workerd 向けに非 Node 版をエクスポートするパッケージを import すると問題が起きることがあります。
回避策として、Vite の SSR モジュールローダーを使い、正しい条件でグローバルセットアップファイルを import するラッパーを作れます。そのあと、Vitest 設定をこのラッパーを指すように変更します。例:
// File: global-setup-wrapper.ts
import { createServer } from "vite";
// Import the actual global setup file with the correct setup
const mod = await viteImport("./global-setup.ts");
export default mod.default;
// Helper to import the file with default node setup
async function viteImport(file: string) {
const server = await createServer({
root: import.meta.dirname,
configFile: false,
server: { middlewareMode: true, hmr: false, watch: null, ws: false },
optimizeDeps: { noDiscovery: true },
clearScreen: false,
});
const mod = await server.ssrLoadModule(file);
await server.close();
return mod;
}// File: vitest.config.ts
import { cloudflareTest } from "@cloudflare/vitest-plugin";
import { defineConfig } from "vitest/config";
export default defineConfig({
plugins: [
cloudflareTest({
// ...
}),
],
test: {
// Replace the globalSetup with the wrapper file
globalSetup: ["./global-setup-wrapper.ts"],
},
});