jest-mongodb: running a real MongoDB inside your Jest tests
Jest preset for MongoDB in-memory server
At a glance
- What is it?
- @shelf/jest-mongodb is a Jest preset that starts a mongodb-memory-server instance for the duration of your test run and hands you a connection URI. It removes the shared-database fixture problem, and it comes with a few sharp edges around watch mode, per-worker databases and ESM configs.
- Who is it for?
- jest-mongodb suits teams whose Jest suite needs real MongoDB semantics, aggregation pipelines or index behaviour that a mock cannot reproduce, and who can accept downloading a mongod binary. It is the wrong tool for a suite that only needs to assert on repository calls, because a real server is slower and heavier than a stub.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the preset does for you
@shelf/jest-mongodb is a Jest preset for running MongoDB memory server, and it is published as a scoped npm package under the Shelf organisation with an MIT licence. The idea is small and useful. Instead of pointing your tests at a shared MongoDB instance on someone's laptop or a container in CI, the preset starts a MongoDB memory server for the test run and exposes a connection URI that your test code can use.@@P@@The alternative it replaces is the usual arrangement: a MongoDB service in CI, a seeded database, a cleanup strategy and a serialisation point where two suites touch the same collections. The memory server removes the service, the seed and the cleanup, at the price of starting a real mongod process per run and downloading a server binary the first time.@@P@@The package is at version 6.x, with 6.0.0 published on 2025-11-13 and 6.0.1 and 6.0.2 both on 2025-11-29. The repository was last pushed on 2026-10-15 and is not archived. The project also points at a sibling package, jest-dynamodb, which does the same job for Amazon DynamoDB, and the two together cover the common cases of testing against a real NoSQL engine.
Installing the preset and the two config files
The package is a development dependency, and the mongodb driver has to be present in your project as well, because the README states it is required as a peer dependency. That is a sensible arrangement: the preset runs the server, but the driver is what your application code uses to talk to it.@@P@@
yarn add @shelf/jest-mongodb --dev@@P@@Then the Jest configuration gets a preset line.@@P@@
module.exports = {
preset: '@shelf/jest-mongodb',
};@@P@@One caveat is worth flagging before you paste it. The README says that if you have a custom jest.config.js you must remove the testEnvironment property, otherwise it conflicts with the preset. That is the kind of instruction that saves an afternoon, because a preset that sets a test environment and a config that sets a different one produce a failure that points at neither.@@P@@The second configuration file, jest-mongodb-config.js, holds the options for the underlying mongodb-memory-server, and the README links to that project's own documentation for the full option list. The shape is a single mongodbMemoryServerOptions object.@@P@@
module.exports = {
mongodbMemoryServerOptions: {
binary: {
version: '4.0.3',
skipMD5: true,
},
autoStart: false,
instance: {},
},
};@@P@@Three fields in that object matter most. The binary version pins which MongoDB server is downloaded, the README's example uses 4.0.3, and skipMD5 is set to true so the download does not need a checksum verification step. autoStart is set to false, which means the server is started by the preset at the right moment rather than when the config module is loaded, and instance is an empty object that the package fills in with the generated database details.
Choosing the database layout: shared, per worker, dynamic or a replica set
This is the part of the configuration where teams get into trouble, because the default behaviour and the per-worker behaviour differ in a way that shows up as flaky tests rather than as an error.@@P@@Sharing one database across the whole run is a single change, adding the dbName field to the instance object.@@P@@
module.exports = {
mongodbMemoryServerOptions: {
binary: {
version: '4.0.3',
skipMD5: true,
},
instance: {
dbName: 'jest',
},
autoStart: false,
},
};@@P@@Giving each Jest worker its own database is the opposite, and it is enabled by setting useSharedDBForAllJestWorkers to false. The README notes that this option does not create a process.env variable, which is the hook into the next section.@@P@@
module.exports = {
mongodbMemoryServerOptions: {
binary: {
skipMD5: true,
},
autoStart: false,
instance: {},
},
useSharedDBForAllJestWorkers: false,
};@@P@@The dynamic database name variant requires passing an empty instance object, which tells the package to generate a database name per worker rather than using a fixed one. The README lists this as the way to use a dynamic database name, and it is the variant that pairs with the per-worker setting.@@P@@Replica set support is configured by adding a replSet object with count and storageEngine fields.@@P@@
module.exports = {
mongodbMemoryServerOptions: {
binary: {
skipMD5: true,
},
autoStart: false,
instance: {},
replSet: {
count: 3,
storageEngine: 'wiredTiger',
},
},
};@@P@@The example uses count 3 with the wiredTiger storage engine, which is the configuration you need for anything that depends on transactions, since a standalone mongod does not provide them. Anyone testing transaction code against this preset has to remember this option, because the failure otherwise appears as a transaction error that looks like a bug in the application.@@P@@The last option is about the environment variable rather than the database. Setting mongoURLEnvName changes the name of the variable the URI is written to, and the README's example renames it to MONGODB_URI, which matters for projects whose code already reads a variable with a different name.
Connecting the client and cleaning up between tests
The package sets process.env.MONGO_URL for convenience, but the README says that using global.__MONGO_URI__ is preferable, because it works with useSharedDBForAllJestWorkers set to false. That is a small detail with a large consequence: if your suite runs with per-worker databases and your code reads the environment variable, every worker in a run can pick up the same URI and your tests interfere with each other.@@P@@The connection pattern is the standard MongoDB driver one.@@P@@
it('should insert a doc into collection', async () => {
const users = db.collection('users');
const mockUser = {_id: 'some-user-id', name: 'John'};
await users.insertOne(mockUser);
const insertedUser = await users.findOne({_id: 'some-user-id'});
expect(insertedUser).toEqual(mockUser);
});@@P@@The database handle comes from connection.db(), and the collection is reached from there, so the test code is ordinary driver code that would work unchanged against a real cluster. That is the property that makes this preset useful for integration-style tests rather than for mocking.@@P@@Cleaning collections between tests is optional and, when you need it, a one-liner in a beforeEach hook.@@P@@
beforeEach(async () => {
await db.collection('COLLECTION_NAME').deleteMany({});
});@@P@@The README links a discussion issue on this, which is where the reasoning about whether to clear collections or to use a fresh database per test sits. The tradeoff is real: deleting everything is fast but leaves indexes and validators behind, so a test that creates an index can affect the next one unless the collection is dropped.
The two rough edges: watch mode and ESM configs
The watch mode gotcha is the kind of bug that costs an afternoon. This package creates a file called globalConfig.json in the project root, and when Jest runs with the --watch flag, changes to that file can cause an infinite loop, because Jest sees the file change and re-runs, which rewrites the file. The fix is one line in the Jest configuration.@@P@@
// jest.config.js
module.exports = {
watchPathIgnorePatterns: ['globalConfig'],
};@@P@@The ESM situation is a recent change in behaviour worth understanding. Node 22.12 turned on require() support for ESM by default, so if your config is an .mjs file with a default export, @shelf/jest-mongodb now imports it automatically, and CommonJS configs are still supported. If you prefer the older behaviour, you can run Jest with the --no-experimental-require-module flag.@@P@@Between them these two items are the practical difference between a smooth setup and a confusing one, and neither is mentioned in most blog posts about this package because both are recent.
CI caching, debug logs and the cost of a real server
Running a real mongod means running a real process, and the first run on a new machine downloads a server binary. The README addresses the CI case directly: cache the MongoDB binary by adding the folder ./node_modules/.cache/mongodb-memory-server/mongodb-binaries to the list of cached paths. That single line is the difference between a fast pipeline and one that downloads tens of megabytes on every run.@@P@@Debugging has its own switch, with the DEBUG environment variable set to jest-mongodb:* to enable the package's debug logs. That is a convention worth knowing because the package will not tell you where to look otherwise.@@P@@The cost side is worth being explicit about. A memory server is a real MongoDB instance, so it exercises real query planning, real index selection, real aggregation pipelines and real type coercion, which is exactly why people use it instead of a mock. It also consumes memory proportional to what your tests write, it takes time to start, and it needs the mongodb driver in your dependency tree even if your application code never talks to MongoDB directly in production.@@P@@The alternative is to mock the repository layer and assert on the calls, which is faster and lighter but proves only that your code asks the right questions, not that the database answers them correctly. The line between the two approaches is usually drawn by whether your code uses features that a mock cannot emulate honestly: aggregation pipelines, unique and sparse indexes, transactions, and text search. If it does, a real server in the test run is not a convenience but the only way to know the answer.
Editorial conclusion
jest-mongodb suits teams whose Jest suite needs real MongoDB semantics, aggregation pipelines or index behaviour that a mock cannot reproduce, and who can accept downloading a mongod binary. It is the wrong tool for a suite that only needs to assert on repository calls, because a real server is slower and heavier than a stub. Verify first that the mongodb driver is installed in your project as a peer dependency, that your CI caches the mongodb-binaries directory, and that you read global.__MONGO_URI__ rather than process.env.MONGO_URL if you use per-worker databases.
Frequently asked questions
What does @shelf/jest-mongodb do?
It is a Jest preset that runs MongoDB memory server during your test run and provides a connection URI, so tests exercise a real MongoDB instead of a shared instance or a mock. The project is MIT licensed and published as a scoped npm package.
How do I install and configure jest-mongodb?
Add `@shelf/jest-mongodb` as a development dependency and make sure the mongodb driver is installed as a peer dependency. Then set `preset: '@shelf/jest-mongodb'` in jest.config.js, removing any testEnvironment property, and create jest-mongodb-config.js with the mongodbMemoryServerOptions for the server.
How do I give each Jest worker its own database?
Set `useSharedDBForAllJestWorkers: false` in jest-mongodb-config.js, and read the connection URI from `global.__MONGO_URI__` rather than from process.env.MONGO_URL, because that option does not create the environment variable.
How do I enable transactions or replica set behaviour in tests?
Add a replSet object to mongodbMemoryServerOptions with count and storageEngine fields. The README's example uses count 3 and the wiredTiger storage engine, which is required for a replica set rather than a standalone server.
Why does Jest watch mode loop with jest-mongodb?
The package creates a globalConfig.json file in the project root, and under the --watch flag changes to it can trigger an infinite loop. Adding `watchPathIgnorePatterns: ['globalConfig']` to the Jest configuration stops it.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/shelfio-jest-mongodb)Was this useful?