INTEGRITY Dokumentace

Napište svůj první test

Tento průvodce vysvětluje, jak začít s @cloudflare/vitest-plugin balíček. Složitější příklady testování s @cloudflare/vitest-plugin, přečtěte si Recepty.

Předpoklady

Nejprve se ujistěte, že:

Definujte konfiguraci Vitest

Ve vašem vitest.config.ts soubor, použijte cloudflareTest() plugin pro konfiguraci integrace Workers Vitest.

Konfiguraci svého Workeru můžete použít z Konfigurační soubor Wrangleru jeho zadáním pomocí wrangler.configPath.

import { cloudflareTest } from "@cloudflare/vitest-plugin";
import { defineConfig } from "vitest/config";

export default defineConfig({
	plugins: [
		cloudflareTest({
			wrangler: { configPath: "./wrangler.jsonc" },
		}),
	],
});

Další konfiguraci můžete také přepsat nebo definovat pomocí miniflare klíč. Ten má přednost před hodnotami nastavenými v konfiguraci Wrangleru.

Tato konfigurace by například přidala KV namespace TEST_NAMESPACE ke kterému se přistupovalo a který byl upravován pouze v testech.

export default defineConfig({
	plugins: [
		cloudflareTest({
			wrangler: { configPath: "./wrangler.jsonc" },
			miniflare: {
				kvNamespaces: ["TEST_NAMESPACE"],
			},
		}),
	],
});

Úplný seznam dostupných možností Miniflare najdete v Miniflare WorkersOptions dokumentace API.

Úplný seznam dostupných konfiguračních možností najdete v Konfigurace.

Definujte typy

Pokud nepoužíváte Typescript, tuto část můžete přeskočit.

Nejprve se ujistěte, že jste spustili wrangler types, který generuje typy pro runtime Cloudflare Workers a Env typu na základě vazeb vašeho Workeru.

Poté přidejte tsconfig.json ve vaší složce testů a přidejte "@cloudflare/vitest-plugin" do pole types, abyste definovali typy pro cloudflare:test. Rovněž byste měli přidat výstup wrangler types do include pole, aby byly k dispozici typy pro runtime Cloudflare Workers.

Příklad test/tsconfig.json

test/tsconfig.json
{
	"extends": "../tsconfig.json",
	"compilerOptions": {
		"moduleResolution": "bundler",
		"types": [
			"@cloudflare/vitest-plugin/types", // provides `cloudflare:test` and `cloudflare:workers` types
		],
	},
	"include": [
		"./**/*.ts",
		"../src/worker-configuration.d.ts", // output of `wrangler types`
	],
}

Psaní testů

Jako příklad použijeme tento jednoduchý Worker. Vrací odpověď 404 pro /404 cestu a "Hello World!" pro všechny ostatní cesty.

src/index.js
export default {
	async fetch(request, env, ctx) {
		if (pathname === "/404") {
			return new Response("Not found", { status: 404 });
		}
		return new Response("Hello World!");
	},
};
src/index.ts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		if (pathname === "/404") {
			return new Response("Not found", { status: 404 });
		}
		return new Response("Hello World!");
	},
} satisfies ExportedHandler<Env>;

Jednotkové testy

Importem Workeru můžeme napsat unit test pro jeho fetch handler.

test/unit.spec.js
import { env } from "cloudflare:workers";
import {
	createExecutionContext,
	waitOnExecutionContext,
} from "cloudflare:test";
import { describe, it, expect } from "vitest";
// Import your worker so you can unit test it
import worker from "../src";

// For now, you'll need to do something like this to get a correctly-typed
// `Request` to pass to `worker.fetch()`.
const IncomingRequest = Request;

describe("Hello World worker", () => {
	it("responds with Hello World!", async () => {
		const request = new IncomingRequest("http://example.com/404");
		// Create an empty context to pass to `worker.fetch()`
		const ctx = createExecutionContext();
		const response = await worker.fetch(request, env, ctx);
		// Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions
		await waitOnExecutionContext(ctx);
		expect(response.status).toBe(404);
		expect(await response.text()).toBe("Not found");
	});
});
test/unit.spec.ts
import { env } from "cloudflare:workers";
import {
	createExecutionContext,
	waitOnExecutionContext,
} from "cloudflare:test";
import { describe, it, expect } from "vitest";
// Import your worker so you can unit test it
import worker from "../src";

// For now, you'll need to do something like this to get a correctly-typed
// `Request` to pass to `worker.fetch()`.
const IncomingRequest = Request<unknown, IncomingRequestCfProperties>;

describe("Hello World worker", () => {
	it("responds with Hello World!", async () => {
		const request = new IncomingRequest("http://example.com/404");
		// Create an empty context to pass to `worker.fetch()`
		const ctx = createExecutionContext();
		const response = await worker.fetch(request, env, ctx);
		// Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions
		await waitOnExecutionContext(ctx);
		expect(response.status).toBe(404);
		expect(await response.text()).toBe("Not found");
	});
});

Integrační testy

Můžete použít exports objekt poskytovaný cloudflare:workers k napsání integračního testu. exports.default.fetch() volá výchozí exportovaný handler definovaný v hlavním Workeru.

test/integration.spec.js
import { exports } from "cloudflare:workers";
import { describe, it, expect } from "vitest";

describe("Hello World worker", () => {
	it("responds with not found and proper status for /404", async () => {
		const response = await exports.default.fetch("http://example.com/404");
		expect(response.status).toBe(404);
		expect(await response.text()).toBe("Not found");
	});
});
test/integration.spec.ts
import { exports } from "cloudflare:workers";
import { describe, it, expect } from "vitest";

describe("Hello World worker", () => {
	it("responds with not found and proper status for /404", async () => {
		const response = await exports.default.fetch("http://example.com/404");
		expect(response.status).toBe(404);
		expect(await response.text()).toBe("Not found");
	});
});

Při použití exports.default.fetch() pro integrační testy běží kód vašeho Workeru ve stejném kontextu jako test runner. To znamená, že pro ovládání Workeru můžete použít globální mocky, ale zároveň to znamená, že váš Worker používá mírně odlišné chování při rozlišování modulů, které poskytuje Vite. Ve většině případů to není problém, ale pokud chcete Workera spustit v čistém prostředí co nejbližším produkčnímu, můžete použít pomocný Worker. Více informací najdete v tento příklad o tom, jak nastavit integrační testy pomocí pomocných Workerů. Použití pomocných Workerů však přináší omezení o kterých byste měli vědět.