跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

准备测试状态

最后更新 查看 MarkdownAgent 设置

集成测试可能需要在运行前向本地存储写入数据。它也可能依赖你不想在测试期间调用的外部服务。使用测试 harness 准备这些状态并替换这些依赖。

访问已配置的绑定

worker.getEnv() 返回为 Worker 配置的变量、密钥和绑定(binding)。你可以为 server.getWorker() 指定类型,以便这些值带有类型。然后使用返回的存储绑定直接从测试中填充数据:

const apiWorker = server.getWorker("api-worker");
const env = await apiWorker.getEnv();

await env.USERS.put("123", JSON.stringify({ name: "Ada" }));
const apiWorker = server.getWorker<ApiEnv>("api-worker");
const env = await apiWorker.getEnv();

await env.USERS.put("123", JSON.stringify({ name: "Ada" }));

应用 D1 迁移

使用 worker.applyD1Migrations(bindingName) 从 Wrangler 配置读取 D1 绑定的迁移设置。它使用配置的 migrations_dir 和 migrations_pattern。没有这些选项时,它会读取相对于配置文件的 migrations 目录中的 .sql 文件。

在存储重置后调用它,以应用尚未运行的迁移。然后使用 worker.getEnv() 访问数据库并填充所需行。

const apiWorker = server.getWorker("api-worker");

beforeEach(async () => {
	await apiWorker.applyD1Migrations("DATABASE");

	const env = await apiWorker.getEnv();
	await env.DATABASE.prepare(
		"INSERT INTO daily_reports (date, user_ids) VALUES (?, ?)",
	)
		.bind("2026-05-29", JSON.stringify(["123", "456"]))
		.run();
});
const apiWorker = server.getWorker<ApiEnv>("api-worker");

beforeEach(async () => {
	await apiWorker.applyD1Migrations("DATABASE");

	const env = await apiWorker.getEnv();
	await env.DATABASE.prepare(
		"INSERT INTO daily_reports (date, user_ids) VALUES (?, ?)",
	)
		.bind("2026-05-29", JSON.stringify(["123", "456"]))
		.run();
});

准备 Durable Object 存储

worker.getDurableObjectStorage() 让你访问基于 SQLite 的 Durable Object 实例的存储。传入其绑定名称或导出的类名。然后按名称或 ID 选择实例。

返回的 handle 会在 Durable Object 内执行 SQL。用它在测试前填充实例,或在 Worker 运行后检查其状态。

const worker = server.getWorker("api-worker");
const storage = await worker.getDurableObjectStorage("COUNTER", {
	name: "user-123",
});

await storage.exec(
	"INSERT INTO counters (id, value) VALUES (?, ?)",
	"user-123",
	0,
);

await worker.fetch("/counter/user-123");

const rows = await storage.exec(
	"SELECT value FROM counters WHERE id = ?",
	"user-123",
);
expect(rows).toEqual([{ value: 1 }]);
const worker = server.getWorker<ApiEnv>("api-worker");
const storage = await worker.getDurableObjectStorage("COUNTER", {
	name: "user-123",
});

await storage.exec(
	"INSERT INTO counters (id, value) VALUES (?, ?)",
	"user-123",
	0,
);

await worker.fetch("/counter/user-123");

const rows = await storage.exec<{ value: number }>(
	"SELECT value FROM counters WHERE id = ?",
	"user-123",
);
expect(rows).toEqual([{ value: 1 }]);

Mock 出站请求

测试 harness 会将 Worker 中的出站 fetch() 请求代理到 Node 环境中的 globalThis.fetch() 函数。这允许你拦截这些请求,并在测试中返回可预测的响应。

以下示例使用 vi.spyOn() mock 单个请求。但你也可以根据偏好使用 Mock Service Worker (MSW) 拦截这些请求。

import { afterEach, test, vi } from "vitest";

afterEach(() => {
	vi.restoreAllMocks();
});

test("loads a user profile", async ({ expect }) => {
	vi.spyOn(globalThis, "fetch").mockImplementation(async (input, init) => {
		const request = new Request(input, init);

		if (request.url === "http://identity.example.com/profile/123") {
			return Response.json({ id: "123", name: "Ada" });
		}

		throw new Error(`Unexpected request: ${request.method} ${request.url}`);
	});

	const worker = server.getWorker();
	const response = await worker.fetch("/users/123");
	expect(await response.json()).toEqual({ id: "123", name: "Ada" });
});
import { afterEach, test, vi } from "vitest";

afterEach(() => {
	vi.restoreAllMocks();
});

test("loads a user profile", async ({ expect }) => {
	vi.spyOn(globalThis, "fetch").mockImplementation(async (input, init) => {
		const request = new Request(input, init);

		if (request.url === "http://identity.example.com/profile/123") {
			return Response.json({ id: "123", name: "Ada" });
		}

		throw new Error(`Unexpected request: ${request.method} ${request.url}`);
	});

	const worker = server.getWorker();
	const response = await worker.fetch("/users/123");
	expect(await response.json()).toEqual({ id: "123", name: "Ada" });
});

使用测试 Worker mock 绑定

当你想控制绑定行为时,请使用 bindingOverrides。它会将绑定路由到在 harness 内运行的测试 Worker。例如,测试 Worker 可以替换 Browser Rendering 绑定,并在不启动浏览器的情况下返回已知截图。

测试 Worker 也可以暴露用于配置其行为的 JSRPC 方法。使用 worker.getExport() 访问测试的默认导出。

const server = createTestHarness({
	workers: [
		{
			configPath: "./workers/web/wrangler.jsonc",
			bindingOverrides: { BROWSER: "mock-browser" },
		},
		// The test Worker (mock-browser) that replaces the Browser Rendering binding
		{ configPath: "./workers/mock-browser/wrangler.jsonc" },
	],
});

// Access the test Worker to configure its behavior or assert its state.
const mockBrowser = await server.getWorker("mock-browser").getExport();

// Configure the screenshot to be returned through the overridden binding.
await mockBrowser.setScreenshot([137, 80, 78, 71]);

const response = await server.fetch("/reports/2026-05-29.png");
expect(await response.bytes()).toEqual(Uint8Array.from([137, 80, 78, 71]));
const server = createTestHarness({
	workers: [
		{
			configPath: "./workers/web/wrangler.jsonc",
			bindingOverrides: { BROWSER: "mock-browser" },
		},
		// The test Worker (mock-browser) that replaces the Browser Rendering binding
		{ configPath: "./workers/mock-browser/wrangler.jsonc" },
	],
});

// Access the test Worker to configure its behavior or assert its state.
const mockBrowser = await server
	.getWorker<unknown, typeof import("../workers/mock-browser")>("mock-browser")
	.getExport();

// Configure the screenshot to be returned through the overridden binding.
await mockBrowser.setScreenshot([137, 80, 78, 71]);

const response = await server.fetch("/reports/2026-05-29.png");
expect(await response.bytes()).toEqual(Uint8Array.from([137, 80, 78, 71]));

这篇文档对您有帮助吗?