Testing
nest-rs-testing boots the real AppBuilder (the four-phase collect →
factories → register → access-graph check) in-process, configures an
HttpTransport without a socket, and exposes a typed client over
poem::test::TestClient.
GraphQL, OpenAPI, and MCP ride the same client because they self-mount as
HTTP endpoints.
The principle: a test is the truth of what production does. No mocked DI graph, no separate test wiring.
Three categories, Rust’s standard model plus the app e2e:
- Unit tests —
#[cfg(test)] mod testsinsidesrc/. Pure logic next to the code under test, with private-item access and no DI boot. - Integration tests —
tests/*.rsat the crate root. The crate’s public API, exercised as an external consumer would. Shared fixtures go intests/common/mod.rs. - End-to-end tests —
TestAppboots the realAppModuleagainst anEphemeralDatabase. The route table, the DI graph, the access-graph check, authn/authz, and the data path all run.
| Where | What it tests | Boots? |
|---|---|---|
crates/<crate>/src/**.rs (#[cfg(test)]) | In-file logic, private items | no |
crates/<crate>/tests/*.rs | Crate’s public API | no |
crates/nest-rs-testing/tests/*.rs | Cross-crate framework wiring | tailored |
apps/<app>/tests/e2e/main.rs | The app’s real top-level module | ✓ real |
Install
Section titled “Install”cargo add --dev nest-rs-testingA dev-dependency — the harness only compiles under cargo test, never into
your release binary.
Picking the right tool
Section titled “Picking the right tool”The three categories are the where. The which depends on the risk you carry. nestrs ships techniques for each — pick what matches, skip what doesn’t:
| Risk you carry | Technique it earns |
|---|---|
| Wiring (DI graph, routes mounted, guards bound) | E2E — TestApp boots the real module tree |
Security policy regressions (Ability::mask, condition_for, WireModelDefaults) | Policy tests — pure unit tests on the policy types |
| Failure modes (401 / 403 / 400 / rollback) | Negative-path tests in the app’s e2e |
| Pure logic — calculations, conversions, validators | Unit tests next to the code |
| Edge cases in parsers and validators | Property-based testing with proptest |
| API contract drift (OpenAPI, GraphQL SDL) | Snapshot tests on /api-json and schema.graphql |
| A framework crate’s public API | Integration tests in the crate’s tests/ |
A small CRUD feature with no calculation and no custom policy can ship with zero unit tests, zero integration tests, and full coverage through its app’s e2e. That is a valid outcome — write what the risk earns, skip what it doesn’t.
Run it
Section titled “Run it”$ nestrs run test unit # unit + integration, no DB Compiling api v0.1.0 Finished `test` profile in 12.4stest result: ok. 142 passed in 0.21s$ nestrs run test e2e # e2e — Postgres required[+] Running container postgres:16-alpinetest create_then_list_users ... oktest result: ok. 14 passed in 4.31s$ nestrs run test cov # full suite with coverage (llvm-cov)The split is by what each command needs to run, not by Rust test
category. nestrs run test unit covers everything that runs without Postgres —
unit tests and integration tests of crates that don’t own
persistence. nestrs run test e2e covers the rest. The full suite is
nestrs run test unit && nestrs run test e2e.
What “done” requires
Section titled “What “done” requires”A wiring bug does not surface in a unit test.
- Every app ships a
tests/e2e/main.rsbooting its real top-level module — it proves the route table, the DI graph, the access-graph check, the authn/authz layers, and the data path are all wired. - HTTP/GraphQL changes require
nestrs run dev <app>+curlagainst the affected endpoint. If you cannot run the binary, say so explicitly rather than claiming green. - No DB mocking in e2e tests — real Postgres via
EphemeralDatabase(testcontainers in CI). Unit tests of pure logic need no DB.
Reference
Section titled “Reference”crates/nest-rs-testing/—TestApp,TestAppBuilder,EphemeralDatabase, the in-process HTTP client.apps/api/tests/e2e/main.rsandapps/auth/tests/e2e/main.rs— the live baseline tests.- The Rust Book, ch. 11.3 and the Cargo Book on integration tests — the underlying conventions.
Going further
Section titled “Going further”- Unit tests — pure logic next to the code, no DI boot.
- Integration tests — a crate’s public API in process.
- End-to-end tests — the real AppModule against live Postgres.
- Publish demo — the exemplar apps these tests ship against.