Skip to content
axxbetadocs
v0.6.3next
GitHub

Seed and query MongoDB

View .mdOpen in Claude

The MongoDB steps put documents in place before your service reads them, and check the documents it writes.

Background:
Given a tracking-db mongo database with the following properties:
| url | mongodb://localhost:27017/parcels?authSource=admin |
| user | parcels |
| password | parcels |

All three properties are required and support ${env:...} and ${sys:...}. The URL must include the database name; authSource defaults to it. The first MongoDB database registered in a scenario is the default.

A seed is a JSON object that maps collection names to arrays of documents. Extended JSON ({"$oid": "..."}, {"$date": "..."}) is supported:

seeds/scans-in-transit.json
{
"scans": [
{
"scanId": "SC-3001-2",
"parcelRef": "PX-TRK-3001",
"status": "IN_TRANSIT",
"location": "Hamburg hub",
"scannedAt": {"$date": "2026-05-05T06:40:00Z"}
},
{
"scanId": "SC-3001-1",
"parcelRef": "PX-TRK-3001",
"status": "PICKED_UP",
"location": "Berlin depot",
"scannedAt": {"$date": "2026-05-04T16:10:00Z"}
}
]
}
Scenario: Tracking shows the latest scan, however the scans arrive
Given a seeds/scans-in-transit.json mongo db seed
And within 10s a selection of at least 1 document is retrieved from the tracking collection where:
| _id | PX-TRK-3001 |
| scanCount | 2 |
When a GET request to /api/parcels/PX-TRK-3001/tracking
And the request is executed
Then the response status code is 200
And the response payload properties are:
| status | IN_TRANSIT |
| lastLocation | Hamburg hub |
| scanCount | 2 |

The service builds its tracking summaries from the scans in the background, so the scenario waits for the summary before it calls the API.

To seed a specific database when the scenario registers more than one:

Given a seeds/scans-in-transit.json MongoDB seed for tracking-db

a seeds/scans-in-transit.json mongo db seed for tracking-db is the same step with the other spelling.

The file path resolves against the resources directories in axx.yaml. See the mongo pack reference.

A document selection finds documents with equality conditions. Dotted field paths reach into nested documents, and the mongo pack reference says how values are read:

Then a selection of documents is retrieved from the scans collection where:
| parcelRef | PX-TRK-3001 |
| status | PICKED_UP |
And the selection has 1 document
And the 1st document for the selection properties are:
| scanId | SC-3001-1 |
| location | Berlin depot |
| scannedAt | 2026-05-04T16:10:00.000Z |

Properties are JSONPaths (location, history[0].status). A value means what it says, and is compared with its type: 2 is an integer, 2.0 a decimal, "2" a string, true a boolean, null null and undefined a field the document lacks (the rules). A document’s numbers keep their BSON types: an int32 or int64 is an integer, a double a decimal, a whole one too (6.0), and a Decimal128 the number it holds (1.50). the 1st document for the selection properties match: takes Java regular expressions instead, matched against the value’s text.

Selections are numbered in the order a scenario retrieves them, and a step without an ordinal checks the first. After a second retrieval (the tracking view before and after a scan, say), name the one a step checks: the 1st document for the 2nd selection properties are:. axx validate warns about a step that checks the first while a later selection goes unchecked.

Like the SQL selections, they are numbered in the order they are retrieved (the 2nd selection has 3 documents), and has more than / has fewer than compare counts.

Then within 10s a selection of at least 1 document is retrieved from the tracking collection where:
| _id | PX-TRK-3001 |
| scanCount | 2 |

The step polls every 500 ms until enough documents match, and fails when the time runs out with fewer. The documents it found are the selection, for later steps to check (the selection has 1 document, or its properties). A selection’s values are typed too: 2 is the integer 2 (2L an int64), 2.0 the decimal, "2" the string, and an object is Extended JSON, like {"$oid": "65a1b2c3d4e5f60718293a4b"} for an ObjectId.

A selection is as strict as a check, though MongoDB’s own equality is not: 2 selects an int32, an int64 or a Decimal128 of 2, but not a double of 2.0, which 2.0 selects; null selects a field that holds null, and undefined a document without the field. A check that misses a document left out for its type says what to write: expected at least 1 document(s) from tracking within 10s (scanCount is the decimal 2.0: write 2.0).

Every query step has an on <service> form for scenarios with more than one MongoDB database.

Seeded documents stay in the database after the scenario, and scenarios run in parallel. Give each scenario’s documents their own keys (PX-TRK-3001 above) and query by them. Scenario isolation explains the approach.