Back to Blog
Lesson 36 of the Cloudflare: Cloudflare for Developers: DNS to CDN course
Cloud NativeAugust 14, 20264 min read

CI/CD: Automated Testing for Cloudflare Workers

Learn how to implement automated testing for your Cloudflare Workers. We cover unit testing with Vitest, Wrangler integration, and building reliable deployments.

Cloudflare WorkersTestingCI/CDQualityAutomation
Lab technician in a white coat using equipment with precision in a sterile environment.

Previously in this course, we covered observability and logging to understand how our code behaves in production. Now, we shift our focus to preventing issues before they reach the edge by implementing automated testing.

Testing isn't just about catching bugs; it’s about creating a "safety net" that allows you to refactor your code with confidence. In the context of serverless, where you can't easily "SSH" into a server to fix a typo, automated testing is your primary defense against regressions.

Understanding the Testing Pyramid

Before diving into code, it helps to understand the testing pyramid. For Cloudflare Workers, we focus heavily on unit tests. These are fast, isolated tests that check individual functions or modules without hitting the real network or databases.

When you write failing unit tests first, you are essentially documenting exactly how your Worker should behave. This discipline prevents the "it works on my machine" syndrome and simplifies the value of regression testing as your application grows.

Setting Up Vitest for Workers

Cloudflare officially supports Vitest for testing Workers. It's fast, integrates perfectly with the Wrangler environment, and allows us to mock Cloudflare-specific bindings like D1 and R2.

First, install the necessary dependencies in your project directory:

Bash
npm install -D vitest @cloudflare/vitest-pool-workers

Next, ensure your vitest.config.ts is configured to use the pool workers environment. Create or update this file in your root:

TYPESCRIPT
import { defineWorkersConfig } from CE9178">'@cloudflare/vitest-pool-workers/config';

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

Writing Your First Worker Unit Test

Let's assume you have a Worker that processes a JSON request and returns a greeting.

The Worker code (src/index.ts):

TYPESCRIPT
export default {
  async fetch(request: Request) {
    const data = await request.json<{ name: string }>();
    return new Response(JSON.stringify({ greeting: CE9178">`Hello, ${data.name}!` }), {
      headers: { CE9178">'content-type': CE9178">'application/json' },
    });
  },
};

The Test code (test/index.spec.ts):

TYPESCRIPT
import { expect, it } from CE9178">'vitest';
import worker from CE9178">'../src/index';

it(CE9178">'returns a personalized greeting', async () => {
  const request = new Request(CE9178">'http://example.com', {
    method: CE9178">'POST',
    body: JSON.stringify({ name: CE9178">'Developer' }),
  });
  
  const response = await worker.fetch(request, {} as any, {} as any);
  const result = await response.json();
  
  expect(result.greeting).toBe(CE9178">'Hello, Developer!');
});

Running Tests via Wrangler

You don't need to deploy to test your code. Wrangler handles the heavy lifting of spinning up a mini-runtime that simulates the Cloudflare environment. Simply run:

Bash
npx vitest

This command will watch your files and re-run tests whenever you save, providing immediate feedback. If you want to integrate this into your CI/CD pipeline later, you'll use npx vitest run to execute the suite once and exit with a pass/fail status.

Hands-on Exercise

  1. Add a test case to the file above that checks for an empty name input (or a missing body) to see if your Worker handles errors gracefully.
  2. Update your package.json to include "test": "vitest" in your scripts section.
  3. Run npm test to verify your suite passes.

Common Pitfalls

  • Assuming Network Access: Unit tests should be isolated. If your code calls an external API, use msw (Mock Service Worker) or fetch-mock to simulate the response. Never make real outbound calls during unit tests.
  • Ignoring Bindings: If your Worker uses D1 or R2, you must mock them in your test. The @cloudflare/vitest-pool-workers package provides built-in support for this, but you must define the environment properly in your config.
  • Over-Testing: Don't test the Cloudflare runtime itself. Test your business logic. If your Worker is just a wrapper around a function, extract that function and test it in isolation.

FAQ

Q: Can I use Jest instead of Vitest? A: You can, but Vitest is the recommended tool for Workers because of its native ESM support and the specific Cloudflare pool integration.

Q: Do these tests run against my real database? A: No. By default, they run against an in-memory instance. You can configure them to use a local D1 instance if needed, but for unit tests, mocks are preferred for speed.

Recap

Automated testing is the foundation of reliable CI/CD. By using Vitest with the Cloudflare pool environment, we can validate our Worker logic locally, catch bugs early, and ensure our production deployments are stable.

Up next: CI/CD: Deployment Pipelines — we will connect these tests to GitHub Actions to automate your production updates.

Similar Posts