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

Написание тестов

В этом руководстве вы узнаете, как настроить Miniflare для тестирования Workers. Miniflare представляет собой низкоуровневый API, который позволяет полностью контролировать запуск и тестирование Workers.

Чтобы использовать Miniflare, убедитесь, что у вас установлена последняя версия Miniflare v3:

npm i -D miniflare@latest

Остальная часть этого руководства демонстрирует концепции с использованием node:test фреймворк для тестирования, но можно использовать любой другой.

Miniflare представляет собой низкоуровневый API с широким набором параметров конфигурации для запуска Worker. В большинстве случаев для тестов потребуется лишь часть доступных параметров, но полный список можно найти в полный справочник по API чтобы изучить возможности Miniflare.

Прежде чем писать тест, необходимо создать Worker. Поскольку Miniflare представляет собой низкоуровневый API, эмулирующий примитивы платформы Cloudflare, ваш Worker должен быть написан на JavaScript, либо вам потребуется интегрировать собственный конвейер сборки в вашу тестовую настройку. Ниже приведён пример Worker только на JavaScript:

src/index.js
export default {
	async fetch(request) {
		return new Response(`Hello World`);
	},
};

Затем вам нужно будет создать первоначальный тестовый файл:

src/index.test.js
import assert from "node:assert";
import test, { after, before, describe } from "node:test";
import { Miniflare } from "miniflare";

describe("worker", () => {
	/**
	 * @type {Miniflare}
	 */
	let worker;

	before(async () => {
		worker = new Miniflare({
			modules: [
				{
					type: "ESModule",
					path: "src/index.js",
				},
			],
		});
		await worker.ready;
	});

	test("hello world", async () => {
		assert.strictEqual(
			await (await worker.dispatchFetch("http://example.com")).text(),
			"Hello World",
		);
	});

	after(async () => {
		await worker.dispose();
	});
});

Вы должны иметь возможность запустить приведённый выше тест через node --test

Выделенные строки в файле теста выше показывают, как настроить Miniflare для запуска JavaScript Worker. После настройки Miniflare ваши отдельные тесты могут отправлять запросы к запущенному Worker и проверять ответы. Это основное ограничение использования Miniflare для тестирования Worker по сравнению с Интеграция Vitest : весь доступ к вашему Worker должен осуществляться через dispatchFetch() Miniflare API, и вы не можете модульно тестировать отдельные функции своего Worker.

В какой среде выполнения запускаются тесты?

При использовании Интеграция Vitest, весь ваш набор тестов выполняется в workerd, вот почему можно тестировать отдельные функции по отдельности. При использовании же другого тестового фреймворка для запуска тестов через Miniflare в изолированной среде выполняется только сам ваш Worker, запущенный в workerd : ваши тестовые файлы выполняются в Node.js. Это означает, что импорт функций из вашего Worker в тестовые файлы может привести к иному поведению, чем во время выполнения, если эти функции полагаются на workerd-специфичное поведение.

Работа с Bindings

dispatchFetch() API из Miniflare позволяет отправлять запросы Worker и проверять корректность полученного ответа, но иногда в тестах требуется работать напрямую с привязками. Для таких случаев Miniflare предоставляет getBindings() API. Например, чтобы получить доступ к переменной окружения в тестах, измените файл теста src/index.test.js следующим образом:

src/index.test.js
...
describe("worker", () => {
	...
	before(async () => {
		worker = new Miniflare({
			...
+			bindings: {
+				FOO: "Hello Bindings",
+			},
		});
		...
	});

	test("text binding", async () => {
		const bindings = await worker.getBindings();
		assert.strictEqual(bindings.FOO, "Hello Bindings");
	});
	...
});

Также можно взаимодействовать с локальными ресурсами, такими как KV и R2, используя тот же API, что и в Worker. Например, вот как можно взаимодействовать с пространством имён KV:

src/index.test.js
...
describe("worker", () => {
	...
	before(async () => {
		worker = new Miniflare({
			...
+			kvNamespaces: ["KV"],
		});
		...
	});

	test("kv binding", async () => {
		const bindings = await worker.getBindings();
		await bindings.KV.put("key", "value");
		assert.strictEqual(await bindings.KV.get("key"), "value");
	});
	...
});

Более сложные Workers

Приведённый выше пример показывает, как тестировать простой Worker, состоящий из одного файла JavaScript. Однако большинство реальных Worker сложнее. Miniflare поддерживает передачу всех составляющих файлов вашего Worker напрямую через API:

new Miniflare({
	modules: [
		{
			type: "ESModule",
			path: "src/index.js",
		},
		{
			type: "ESModule",
			path: "src/imported.js",
		},
	],
});

По мере роста вашего Worker это может стать не совсем удобным. Чтобы упростить задачу, Miniflare умеет также обходить граф модулей и автоматически определять, какие модули нужно включить:

new Miniflare({
	scriptPath: "src/index-with-imports.js",
	modules: true,
	modulesRules: [{ type: "ESModule", include: ["**/*.js"] }],
});

Пользовательские сборки

На практике Workers часто пишут не на чистом JavaScript, а в виде нескольких файлов TypeScript, которые импортируют пакеты npm и другие зависимости, а затем собираются инструментом сборки. При тестировании Worker напрямую через Miniflare этот инструмент сборки нужно запускать перед тестами. Как именно запускается сборка, зависит от конкретного тестового фреймворка, но для node:test это, вероятно, было бы в setup() хук. Например, если вы используете Wrangler чтобы собрать и развернуть Worker, можно запустить wrangler build команду следующим образом:

before(() => {
	spawnSync("npx wrangler build -c wrangler-build.json", {
		shell: true,
		stdio: "pipe",
	});
});