Skip to Content

E2E Test Generation

Configure e2e in nestia.config.ts and npx nestia e2e writes a starter end-to-end test for every @TypedRoute-decorated method in your project. Each test:

  • Picks a random valid input from the route’s DTO type (via typia.random<T>()).
  • Calls the generated SDK function (no fetch strings).
  • Asserts that the response matches the declared return type.

That’s the schema-contract net: every route gets covered, on every CI run, with zero hand-written boilerplate. Your own business-logic tests live alongside them.


Enable

nestia.config.ts
import { INestiaConfig } from "@nestia/sdk"; import { NestFactory } from "@nestjs/core"; import { AppModule } from "./src/AppModule"; const config: INestiaConfig = { input: () => NestFactory.create(AppModule), output: "src/api", e2e: "test", // output directory for the generated suite }; export default config;

Run:

Terminal
npx nestia e2e

Output: test/features/api/<controller-path>/test_api_<route>.ts (one file per endpoint).


Anatomy of a generated test

test/features/api/articles/test_api_articles_create.ts (generated)
import typia, { Primitive } from "typia"; import api from "@my-app/api"; import type { IArticle } from "@my-app/api/lib/structures/IArticle"; export const test_api_articles_create = async ( connection: api.IConnection, ): Promise<void> => { const output: IArticle = await api.functional.articles.create( connection, typia.random<Primitive<IArticle.ICreate>>(), ); typia.assert(output); };

Three lines that matter:

  1. typia.random<Primitive<IArticle.ICreate>>() β€” synthesizes a schema-valid request body.
  2. api.functional.articles.create(...) β€” the generated SDK call against connection.
  3. typia.assert(output) β€” verifies the response matches IArticle.

If the schema drifts (server returns a different shape), the assert fails on the next CI run.

Re-running npx nestia e2e overwrites these files. Keep them auto-generated and add your hand-written scenarios in sibling files (the runner picks up anything matching test_*).


Run the suite

@nestia/e2e’s DynamicExecutor walks the test directory, finds every test_* function, and runs them in series. A typical runner:

test/index.ts
import { DynamicExecutor } from "@nestia/e2e"; import { NestFactory } from "@nestjs/core"; import { AppModule } from "../src/AppModule"; const main = async () => { const app = await NestFactory.create(AppModule); await app.listen(0); const port = (app.getHttpServer().address() as any).port; const report = await DynamicExecutor.validate({ prefix: "test_", parameters: () => [{ host: `http://localhost:${port}` }], })(__dirname + "/features"); console.log(report); await app.close(); }; main().catch(console.error);

Run with npx ttsx test/index.ts. Exit code reflects pass/fail; plug into CI.


Mixing generated tests with hand-written ones

The convention is one directory per controller / domain, with both auto and hand-written files:

test/features/api/articles/ β”œβ”€β”€ test_api_articles_create.ts # generated β€” schema contract β”œβ”€β”€ test_api_articles_list.ts # generated β€” schema contract β”œβ”€β”€ test_api_articles_admin_sees_all.ts # hand-written β€” business rule └── test_api_articles_archive_idempotent.ts # hand-written β€” business rule

DynamicExecutor finds them all by the test_ prefix. The auto-generated tests prove the schema works; your hand-written tests prove the rules work.


Re-using the SDK for benchmarks

The same test files drive @nestia/benchmark β€” point it at the same directory and you get a load report:

test/benchmark/index.ts
import { DynamicBenchmarker } from "@nestia/benchmark"; const report: DynamicBenchmarker.IReport = await DynamicBenchmarker.master({ servant: `${__dirname}/servant.js`, count: 1_024, threads: 4, simultaneous: 32, }); await fs.promises.writeFile("BENCHMARK.md", DynamicBenchmarker.markdown(report));
test/benchmark/servant.ts
import { DynamicBenchmarker } from "@nestia/benchmark"; DynamicBenchmarker.servant({ connection: { host: "http://127.0.0.1:37001" }, location: `${__dirname}/../features`, parameters: (connection) => [connection], prefix: "test_api_", });

The report gives the mean, standard deviation, minimum, and maximum of the response time, in total and per endpoint, with success counts and memory usage, as markdown. See E2E β†’ Benchmark for the full configuration.


See also

Last updated on