Testing Cloudflare Workers with Vitest and Miniflare
Yuki Tanaka
·
·
11 views
Unit testing Workers used to mean mocking the entire runtime. The Workers Vitest pool gives you a real Workers runtime inside your test suite — no mocks required.
The Old Way: Mocking Fetch
Before the Workers Vitest pool, testing a Worker meant mocking fetch, Request, Response, and hoping your mocks matched the real behaviour. This led to tests that passed locally but broke in production.
Enter @cloudflare/vitest-pool-workers
The @cloudflare/vitest-pool-workers package runs your tests inside a real Workers runtime using Miniflare. You get access to D1, KV, R2, and all other bindings — backed by local in-memory implementations.
Setup
npm install -D vitest @cloudflare/vitest-pool-workers
// vitest.config.ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
wrangler: { configPath: "./wrangler.jsonc" }
}
}
}
});
Writing a Test
import { env, SELF } from "cloudflare:test";
import { describe, it, expect, beforeAll } from "vitest";
beforeAll(async () => {
await env.DB.exec(`INSERT INTO articles (slug, title) VALUES ('test', 'Test')`);
});
describe("GET /api/articles", () => {
it("returns a list of articles", async () => {
const response = await SELF.fetch("http://localhost/api/articles", {
headers: { Authorization: "Bearer test-token" }
});
expect(response.status).toBe(200);
const body = await response.json();
expect(body.articles).toBeInstanceOf(Array);
});
});
Tips
- Use
env.DB.batch()inbeforeAll/afterEachto set up and tear down fixtures SELF.fetch()exercises the real routing layer — prefer it over unit-testing handlers in isolation- Miniflare resets storage between test files but not between tests in the same file
← Back to articles
11 views