Assertions

Ordered snapshots

documents(): the “exactly these documents, in this order” assertion, for audit logs, outboxes and any collection whose whole shape is the thing under test.

What a snapshot is

Every other collection assertion re-reads the store when it runs. documents() is the exception: it reads the collection once, at the moment of the call, and all further steps work on that one list. That is what makes sortedBy and the failure diff describe one consistent set of documents.

Java
assertThatCollection("audit_log")
    .documents()                         // snapshot taken here, once
    .sortedBy("timestamp")               // collections are unordered; sort explicitly
    .ignoringFields("_id", "createdAt")  // field names or JsonPaths, your choice
    .containsExactlyJson(
        """
        {"event": "ORDER_PLACED",  "orderId": "ord-1"}
        """,
        """
        {"event": "PAYMENT_TAKEN", "orderId": "ord-1"}
        """);

sortedBy

Compares in ascending order of one field, which may be a dotted path, instead of the store's natural order. A document without the field sorts first, and ties keep their inbound order.

The sort order is a stable total order for assertion purposes: numbers by value across BSON types, dates and strings naturally, and deliberately not MongoDB's cross-type sort order. Server-fidelity sorting is what find().sort(...) is for; this is about giving the diff table a reproducible row order.

ignoringFields

Deletes fields from both sides before comparing. This is how a generated _id or an audit timestamp is excused without spelling it out in every expected document. It takes either vocabulary: a field name ("_id", "customer.tier") or a JsonPath ("$.lines[0].sku"). Anything not starting with $ is prefixed internally. Repeated calls accumulate. A path that does not exist in a document is simply ignored; a string that is not a valid path at all throws IllegalArgumentException.

containsExactlyJson

The snapshot holds exactly these documents, in this order. The comparison is structural, not textual: both sides are parsed, so key order and whitespace are irrelevant, and each expected document is written in the same relaxed Extended JSON the rest of the library speaks.

On failure the headline states the expectation with its qualifiers, and the diff table shows expected against actual row by row, with ▶ in the gutter of the first row that does not line up. This is genuine output from a real failing test:

text
java.lang.AssertionError:
Expected collection <test.audit_log> to contain exactly 2 documents (sorted by <seq>, ignoring $._id, $.seq), but they differ at index 1.
    | idx | expected                             | actual
  --+-----+--------------------------------------+------------------------------------
    | 0   | {event=ORDER_PLACED, orderId=ord-1}  | {event=ORDER_PLACED, orderId=ord-1}
  ▶ | 1   | {event=PAYMENT_TAKEN, orderId=ord-1} | {event=REFUNDED, orderId=ord-1}

When the counts differ, the headline says but it holds 3. instead, and rows missing from either side render as (absent). Long values are abbreviated at 96 characters, the same width every table in the library uses.

documents(): the escape hatch

Calling documents() again, on the snapshot assertion, returns the sorted snapshot as a plain List<Document>. For an assertion this class does not have a word for. For the raw unsorted list without the assertion machinery, MongoCollectionReader.readDocuments(name) is the direct route.

Java
List<Document> sorted = assertThatCollection("audit_log")
    .documents()
    .sortedBy("timestamp")
    .documents();   // the sorted snapshot itself, as plain Documents

assertThat(sorted).allSatisfy(d ->
    assertThat(d.getDate("timestamp")).isAfter(cutoff));