INTEGRITY Документация

Подготовьте тестовое состояние

Интеграционному тесту может потребоваться наличие данных в локальном хранилище перед запуском. Он также может зависеть от внешних сервисов, которые нежелательно вызывать во время теста. Используйте тестовый набор инструментов (test harness), чтобы подготовить это состояние и заменить эти зависимости.

Доступ к настроенным привязкам

worker.getEnv() возвращает переменные, секреты и привязки (bindings), настроенные для Worker. Вы можете указать типы для 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) чтобы прочитать настройки миграции для привязки D1 из конфигурации Wrangler. Используется настроенный migrations_dir и migrations_pattern. Без этих параметров он считывает .sql файлы из migrations каталог относительно файла конфигурации.

Вызовите этот метод после сброса хранилища, чтобы применить еще не выполненные миграции. Затем обращайтесь к базе данных через 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() даёт доступ к хранилищу экземпляра Durable Object на основе SQLite. Передайте имя его привязки или имя экспортированного класса. Затем выберите экземпляр по имени или ID.

Возвращённый дескриптор выполняет SQL внутри Durable Object. Используйте его, чтобы заполнить экземпляр данными перед тестом или проверить его состояние после выполнения 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 }]);

Подмена исходящих запросов

Тестовое окружение проксирует исходящие fetch() запросы из ваших Workers через globalThis.fetch() функция в вашем окружении Node. Это позволяет перехватывать такие запросы и возвращать предсказуемый ответ в тестах.

Пример с использованием vi.spyOn() чтобы замокать один запрос. Но также можно использовать 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" });
});

Мокирование привязок с помощью тестовых Workers

Используйте bindingOverrides когда нужно управлять поведением привязки. Она направляет привязку к тестовому 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]));