---
inclusion: fileMatch
fileMatchPattern: "src/test/**"
---

# MongoDB integration tests: Bonsai

This project tests MongoDB code with **Bonsai**. Use `io.typecheck:bonsai-spring-boot`
for Spring Boot tests and `io.typecheck:bonsai-junit` for plain JUnit 5. Bonsai is an
embedded, in-process MongoDB. No Docker, no `mongod`, no Testcontainers.

## Rules

- **Imports**: Spring Boot tests use
  `io.typecheck.bonsai.spring.EnableMongoEmulator`; plain JUnit tests use
  `io.typecheck.bonsai.junit.EnableMongoEmulator`. Never mix them up. The generic
  one on a `@SpringBootTest` leaves the app unwired.
- **Naming**: `"orders"` = default database; `"billing.invoices"` = database `billing`.
  Same rule for annotations, seeds, readers and assertions.
- **Seeding**: class-level `@MongoSeed` for suite fixtures (re-applied after every
  cleanup), method-level for per-test data, `MongoTestData.seed(...)` with a
  `Map.of(...)` to bind `${...}` placeholders programmatically,
  `SpringMongoTestData.insert(...)` for typed entities through the app's converter.
  Built-ins: `${#objectId}`, `${#uuid}`, `${#now}`, `${#now+PT2H}`, `${#today}`;
  inline defaults `${name:default}`.
- **Assertions**: static-import `MongoAssertions.*`: `assertThatCollection(name)`,
  `assertThatDocument(doc)`, `assertThatChoreography()` for multi-collection flows,
  `.documents().sortedBy(...).ignoringFields(...).containsExactlyJson(...)` for ordered
  snapshots, `MongoFieldMatchers` for field types.
- **Async**: `MongoTestAwait.untilCount/untilExists/untilAbsent/until`: never
  `Thread.sleep`.
- **Cleanup is automatic** (per-method drop-databases + declared-collections/index/seed re-creation). Never
  add `@DirtiesContext` for Mongo state, and never write `@TestConfiguration` Mongo
  beans. Bean overrides rewire production beans.
- **Transactions**: `@Transactional` works, and the whole collection surface is
  transaction-aware: `findAndModify`, `aggregate` (incl. `$lookup`), the `ClientSession`
  `bulkWrite` overloads and `distinct` all run inside a transaction with
  read-your-own-writes and byte-exact rollback. Nothing fails fast merely because a
  transaction is active; isolation is content-based, not a snapshot.
- **Parallel**: parallel classes yes; parallel methods within one class are refused at
  `beforeAll`. Use `junit.jupiter.execution.parallel.mode.classes.default=concurrent`.
- **Passthrough**: `mode=passthrough` + `passthrough.uri` runs the same suite against a
  real MongoDB; cleanup drops the known databases on that server. Use a dedicated test
  server only.
- **Do not invent APIs.** `MongoTestData` is static-only (no fluent builder); there is no
  `assertThatDatabase`; properties live under `bonsai.*` (Boot 4:
  `spring.mongodb.*`, not `spring.data.mongodb.*`).
- **Durability**: the file-backed debug store (`bonsai.durability.directory`) needs
  `io.typecheck:bonsai-durability` at test scope. Do not hand-add
  `org.dizitart:nitrite-mvstore-adapter`; the artifact delivers it version-aligned.
  Without it, durability mode fails at runtime with `MVStoreModule` missing.
- Target release is `3.6.0` (development: `3.6.0-SNAPSHOT`), distributed through Maven Central, group `io.typecheck`; scope `test` only.
- **Coming from 1.x?** Bonsai 2.0 is the rename of `mongo-test-utils` /
  `spring-mongo-test-utils` (group `io.gitlab.guisseppe`). Behaviour is unchanged;
  the names are not: `io.gitlab.guisseppe.mongo.test*` → `io.typecheck.bonsai*`,
  `@MongoTestServer` → `@EnableMongoEmulator`, `spring.mongodb.test.*` →
  `bonsai.*`, `mongo.test.durability.directory` → `bonsai.durability.directory`,
  `MTU_*` → `BONSAI_*`, hand-added `nitrite-mvstore-adapter` → `bonsai-durability`.
  `spring.mongodb.uri` / `.host` / `.port` / `.database` are Spring's own and keep
  their names. Never leave 1.x and 2.0 on the same test classpath, and never leave a
  `spring.mongodb.test.*` key behind. It is not aliased, so it binds to nothing and the
  setting silently reverts to its default.
