Testing

Test your server routes, plugins and runtime utilities with Vitest.

Vitest picks up the nitro() plugin from your Vite config. Test files run in the nitro Vite environment, so nitro/* runtime utilities, routes, plugins and runtime config work the same as in your server code.

#Setup

Install vitest as a dev dependency:

npm i -D vitest

No extra config is needed, as long as vite.config.ts (or vitest.config.ts) registers the nitro() plugin. A project with only a nitro.config.ts needs to add one:

vite.config.ts
import { defineConfig } from "vite";
import { nitro } from "nitro/vite";

export default defineConfig({
  plugins: [nitro()],
});

Then run vitest.

#Writing tests

Use serverFetch to send requests to your Nitro app, and call runtime utilities directly:

test/app.test.ts
import { expect, test } from "vitest";
import { serverFetch } from "nitro";
import { useKV } from "nitro/kv";

test("GET /api/hello", async () => {
  const res = await serverFetch("/api/hello");
  expect(await res.json()).toEqual({ hello: "world" });
});

test("kv", async () => {
  await useKV().setItem("foo", "bar");
  expect(await useKV().getItem("foo")).toBe("bar");
});

Tests run in Vitest workers, without starting the Nitro dev server. With Vitest's default isolation, each test file gets its own Nitro app instance, and its close hooks run when the file finishes.

vi.mock works as usual, including for modules imported by your routes and Nitro plugins: the app is created after the test file's mocks are registered.

Read more in Examples > Vitest.

#Watch mode

In watch mode, editing a route, middleware or plugin reruns the tests that use the app. Adding or removing one rescans the server directories first, and changing the Nitro config restarts Vitest.

#SSR entry

Pages rendered by an SSR entry (entry-server.ts) work with serverFetch too. In tests, service entries such as ssr are loaded in the nitro environment rather than their own environment, so plugins and options that only apply to that environment are not used.

Frameworks that rely on several server environments (such as React Server Components) are not supported yet.

#Choosing the environment

The nitro test environment is used when test.environment is not set. To use another environment, set test.environment and opt individual files back in with a // @vitest-environment nitro comment, or the other way around.

Projects defined inline in test.projects don't get the default environment. Set environment: "nitro" in each project that runs server tests:

vite.config.ts
import { defineConfig } from "vitest/config";
import { nitro } from "nitro/vite";

export default defineConfig({
  plugins: [nitro()],
  test: {
    projects: [{ extends: true, test: { name: "server", environment: "nitro" } }],
  },
});

#Limitations

  • The vmThreads and vmForks pools don't support the nitro environment.
  • Tests always run in Node.js: the devServer.runner option, including the one set by a preset (such as miniflare for Cloudflare), is not used, so platform modules and bindings (such as cloudflare:workers) are not available.

Nitro  builds full-stack servers that deploy anywhere.