shwldshwld15 days ago

Cloudflare D1のテストでは readD1Migrations + applyD1Migrations でマイグレーションを適用する

@cloudflare/vitest-pool-workers でD1を使うテストを書くとき、テストヘルパーにCREATE TABLE文をハードコードしていた。マイグレーションファイルを追加するたびにテストヘルパーも手動で同期する必要があり、乖離してテストが壊れることがあった。

@cloudflare/vitest-pool-workers が提供する readD1MigrationsapplyD1Migrations を使えば、本番と同じマイグレーションファイルをテストDBにも適用できる。

// vitest.config.ts(Node.jsコンテキスト)
import {
  defineWorkersConfig,
  readD1Migrations,
} from "@cloudflare/vitest-pool-workers/config";

export default defineWorkersConfig(async () => {
  const migrationsPath = path.join(__dirname, "migrations");
  const migrations = await readD1Migrations(migrationsPath);
  return {
    test: {
      poolOptions: {
        workers: {
          miniflare: {
            d1Databases: { DB: { migrationsPath } },
            bindings: { TEST_MIGRATIONS: migrations },
          },
        },
      },
    },
  };
});
// test/helpers.ts(Workerコンテキスト)
import { env } from "cloudflare:test";
import { applyD1Migrations } from "cloudflare:test";

export async function resetDatabase() {
  await applyD1Migrations(env.DB, env.TEST_MIGRATIONS);
  // DELETE文でデータだけクリア(テーブル作成は不要)
  await env.DB.exec("DELETE FROM orders; DELETE FROM users;");
}

ハマりどころ:

  • readD1Migrations はNode.jsコンテキスト(vitest.config.ts)で呼ぶ。Worker内では fs が使えない
  • applyD1Migrationscloudflare:test からimportする。Workerコンテキスト専用
  • wrangler.tomlmigrations_dir を設定するだけでは自動適用されない。明示的にAPIを呼ぶ必要がある