---
title: Configuration · Cloudflare Workers docs
description: Vitest configuration specific to the Workers integration.
lastUpdated: 2025-04-10T14:17:11.000Z
chatbotDeprioritize: false
source_url:
  html: https://developers.cloudflare.com/workers/testing/vitest-integration/configuration/
  md: https://developers.cloudflare.com/workers/testing/vitest-integration/configuration/index.md
---

The Workers Vitest integration provides additional configuration on top of Vitest's usual options using the [`defineWorkersConfig()`](https://developers.cloudflare.com/workers/testing/vitest-integration/configuration/#defineworkersconfigoptions) API.

An example configuration would be:

```ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";


export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: {
          configPath: "./wrangler.toml",
        },
      },
    },
  },
});
```

Warning

Custom Vitest `environment`s or `runner`s are not supported when using the Workers Vitest integration.

## APIs

The following APIs are exported from the `@cloudflare/vitest-pool-workers/config` module.

### `defineWorkersConfig(options)`

Ensures Vitest is configured to use the Workers integration with the correct module resolution settings, and provides type checking for [WorkersPoolOptions](#workerspooloptions). This should be used in place of the [`defineConfig()`](https://vitest.dev/config/file.html) function from Vitest.

It also accepts a `Promise` of `options`, or an optionally-`async` function returning `options`.

```ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";


export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        // Refer to type of WorkersPoolOptions...
      },
    },
  },
});
```

### `defineWorkersProject(options)`

Use [`defineWorkersProject`](#defineworkersprojectoptions) with [Vitest Workspaces](https://vitest.dev/guide/workspace) to specify a different configuration for certain tests. It should be used in place of the [`defineProject()`](https://vitest.dev/guide/workspace) function from Vitest.

Similar to [`defineWorkersConfig()`](#defineworkersconfigoptions), this ensures Vitest is configured to use the Workers integration with the correct module resolution settings, and provides type checking for [WorkersPoolOptions](#workerspooloptions).

It also accepts a `Promise` of `options`, or an optionally-`async` function returning `options`.

```ts
import { defineWorkspace, defineProject } from "vitest/config";
import { defineWorkersProject } from "@cloudflare/vitest-pool-workers/config";


const workspace = defineWorkspace([
  defineWorkersProject({
    test: {
      name: "Workers",
      include: ["**/*.worker.test.ts"],
      poolOptions: {
        workers: {
          // Refer to type of WorkersPoolOptions...
        },
      },
    },
  }),


  // ...
]);


export default workspace;
```

### `buildPagesASSETSBinding(assetsPath)`

Creates a Pages ASSETS binding that serves files insides the `assetsPath`. This is required if you uses `createPagesEventContext()` or `SELF` to test your **Pages Functions**. Refer to the [Pages recipe](https://developers.cloudflare.com/workers/testing/vitest-integration/recipes) for a full example.

```ts
import path from "node:path";
import {
  buildPagesASSETSBinding,
  defineWorkersProject,
} from "@cloudflare/vitest-pool-workers/config";


export default defineWorkersProject(async () => {
  const assetsPath = path.join(__dirname, "public");


  return {
    test: {
      poolOptions: {
        workers: {
          miniflare: {
            serviceBindings: {
              ASSETS: await buildPagesASSETSBinding(assetsPath),
            },
          },
        },
      },
    },
  };
});
```

### `readD1Migrations(migrationsPath)`

Reads all [D1 migrations](https://developers.cloudflare.com/d1/reference/migrations/) stored at `migrationsPath` and returns them ordered by migration number. Each migration will have its contents split into an array of individual SQL queries. Call the [`applyD1Migrations()`](https://developers.cloudflare.com/workers/testing/vitest-integration/test-apis/#d1) function inside a test or [setup file](https://vitest.dev/config/#setupfiles) to apply migrations. Refer to the [D1 recipe](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/d1) for an example project using migrations.

```ts
import path from "node:path";
import {
  defineWorkersProject,
  readD1Migrations,
} from "@cloudflare/vitest-pool-workers/config";


export default defineWorkersProject(async () => {
  // Read all migrations in the `migrations` directory
  const migrationsPath = path.join(__dirname, "migrations");
  const migrations = await readD1Migrations(migrationsPath);


  return {
    test: {
      setupFiles: ["./test/apply-migrations.ts"],
      poolOptions: {
        workers: {
          miniflare: {
            // Add a test-only binding for migrations, so we can apply them in a setup file
            bindings: { TEST_MIGRATIONS: migrations },
          },
        },
      },
    },
  };
});
```

## `WorkersPoolOptions`

* `main`: string optional

  * Entry point to Worker run in the same isolate/context as tests. This option is required to use `import { SELF } from "cloudflare:test"` for integration tests, or Durable Objects without an explicit `scriptName` if classes are defined in the same Worker. This file goes through Vite transforms and can be TypeScript. Note that `import module from "<path-to-main>"` inside tests gives exactly the same `module` instance as is used internally for the `SELF` and Durable Object bindings. If `wrangler.configPath` is defined and this option is not, it will be read from the `main` field in that configuration file.

* `isolatedStorage`: boolean optional

  * Enables per-test isolated storage. If enabled, any writes to storage performed in a test will be undone at the end of the test. The test's storage environment is copied from the containing suite, meaning `beforeAll()` hooks can be used to seed data. If this option is disabled, all tests will share the same storage. `.concurrent` tests are not supported when isolated storage is enabled. Refer to [Isolation and concurrency](https://developers.cloudflare.com/workers/testing/vitest-integration/isolation-and-concurrency/) for more information on the isolation model.

  * Defaults to `true`.

    Illustrative example

    ```ts
    import { env } from "cloudflare:test";
    import { beforeAll, beforeEach, describe, test, expect } from "vitest";


    // Get the current list stored in a KV namespace
    async function get(): Promise<string[]> {
      return (await env.NAMESPACE.get("list", "json")) ?? [];
    }
    // Add an item to the end of the list
    async function append(item: string) {
      const value = await get();
      value.push(item);
      await env.NAMESPACE.put("list", JSON.stringify(value));
    }


    beforeAll(() => append("all"));
    beforeEach(() => append("each"));


    test("one", async () => {
      // Each test gets its own storage environment copied from the parent
      await append("one");
      expect(await get()).toStrictEqual(["all", "each", "one"]);
    });
    // `append("each")` and `append("one")` undone
    test("two", async () => {
      await append("two");
      expect(await get()).toStrictEqual(["all", "each", "two"]);
    });
    // `append("each")` and `append("two")` undone


    describe("describe", async () => {
      beforeAll(() => append("describe all"));
      beforeEach(() => append("describe each"));


      test("three", async () => {
        await append("three");
        expect(await get()).toStrictEqual([
          // All `beforeAll()`s run before `beforeEach()`s
          "all",
          "describe all",
          "each",
          "describe each",
          "three",
        ]);
      });
      // `append("each")`, `append("describe each")` and `append("three")` undone
      test("four", async () => {
        await append("four");
        expect(await get()).toStrictEqual([
          "all",
          "describe all",
          "each",
          "describe each",
          "four",
        ]);
      });
      // `append("each")`, `append("describe each")` and `append("four")` undone
    });
    ```

* `singleWorker`: boolean optional

  * Runs all tests in this project serially in the same Worker, using the same module cache. This can significantly speed up execution if you have lots of small test files. Refer to the [Isolation and concurrency](https://developers.cloudflare.com/workers/testing/vitest-integration/isolation-and-concurrency/) page for more information on the isolation model.

  * Defaults to `false`.

* `miniflare`: `SourcelessWorkerOptions & { workers?: WorkerOptions\[]; }` optional

  * Use this to provide configuration information that is typically stored within the [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/), such as [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/), [compatibility dates](https://developers.cloudflare.com/workers/configuration/compatibility-dates/), and [compatibility flags](https://developers.cloudflare.com/workers/configuration/compatibility-flags/). The `WorkerOptions` interface is defined [here](https://github.com/cloudflare/workers-sdk/tree/main/packages/miniflare#interface-workeroptions). Use the `main` option above to configure the entry point, instead of the Miniflare `script`, `scriptPath`, or `modules` options.

  * If your project makes use of multiple Workers, you can configure auxiliary Workers that run in the same `workerd` process as your tests and can be bound to. Auxiliary Workers are configured using the `workers` array, containing regular Miniflare [`WorkerOptions`](https://github.com/cloudflare/workers-sdk/tree/main/packages/miniflare#interface-workeroptions) objects. Note that unlike the `main` Worker, auxiliary Workers:

    * Cannot have TypeScript entrypoints. You must compile auxiliary Workers to JavaScript first. You can use the [`wrangler deploy --dry-run --outdir dist`](https://developers.cloudflare.com/workers/wrangler/commands/#deploy) command for this.
    * Use regular Workers module resolution semantics. Refer to the [Isolation and concurrency](https://developers.cloudflare.com/workers/testing/vitest-integration/isolation-and-concurrency/#modules) page for more information.
    * Cannot access the [`cloudflare:test`](https://developers.cloudflare.com/workers/testing/vitest-integration/test-apis/) module.
    * Do not require specific compatibility dates or flags.
    * Can be written with the [Service Worker syntax](https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/#service-worker-syntax).
    * Are not affected by global mocks defined in your tests.

* `wrangler`: `{ configPath?: string; environment?: string; }` optional

  * Path to [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/) to load `main`, [compatibility settings](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) and [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) from. These options will be merged with the `miniflare` option above, with `miniflare` values taking precedence. For example, if your Wrangler configuration defined a [service binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) named `SERVICE` to a Worker named `service`, but you included `serviceBindings: { SERVICE(request) { return new Response("body"); } }` in the `miniflare` option, all requests to `SERVICE` in tests would return `body`. Note `configPath` accepts both `.toml` and `.json` files.

  * The environment option can be used to specify the [Wrangler environment](https://developers.cloudflare.com/workers/wrangler/environments/) to pick up bindings and variables from.

## `WorkersPoolOptionsContext`

* `inject`: typeof import("vitest").inject

  * The same `inject()` function usually imported from the `vitest` module inside tests. This allows you to define `miniflare` configuration based on injected values from [`globalSetup`](https://vitest.dev/config/#globalsetup) scripts. Use this if you have a value in your configuration that is dynamically generated and only known at runtime of your tests. For example, a global setup script might start an upstream server on a random port. This port could be `provide()`d and then `inject()`ed in the configuration for an external service binding or [Hyperdrive](https://developers.cloudflare.com/hyperdrive/). Refer to the [Hyperdrive recipe](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/hyperdrive) for an example project using this provide/inject approach.

    Illustrative example

    ```ts
    // env.d.ts
    declare module "vitest" {
      interface ProvidedContext {
        port: number;
      }
    }


    // global-setup.ts
    import type { GlobalSetupContext } from "vitest/node";
    export default function ({ provide }: GlobalSetupContext) {
      // Runs inside Node.js, could start server here...
      provide("port", 1337);
      return () => {
        /* ...then teardown here */
      };
    }


    // vitest.config.ts
    import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
    export default defineWorkersConfig({
      test: {
        globalSetup: ["./global-setup.ts"],
        pool: "@cloudflare/vitest-pool-workers",
        poolOptions: {
          workers: ({ inject }) => ({
            miniflare: {
              hyperdrives: {
                DATABASE: `postgres://user:pass@example.com:${inject("port")}/db`,
              },
            },
          }),
        },
      },
    });
    ```

## `SourcelessWorkerOptions`

Sourceless `WorkerOptions` type without `script`, `scriptPath`, or `modules` properties. Refer to the Miniflare [`WorkerOptions`](https://github.com/cloudflare/workers-sdk/tree/main/packages/miniflare#interface-workeroptions) type for more details.

```ts
type SourcelessWorkerOptions = Omit<
  WorkerOptions,
  "script" | "scriptPath" | "modules" | "modulesRoot"
>;
```
