I am writing some integration and system tests for my NodeJS application using a MongoDB database. The test framework I use is Mocha and Supertest. Is it possible to setup MongoDB as an in-memory database which I can use to only test which then wipes away all my collections and documents when the test is done?
MongoDB is not an in-memory database. Although it can be configured to run that way. But it makes liberal use of cache, meaning data records kept memory for fast retrieval, as opposed to on disk. There is much bad information on StackOverflow about what to do when your server runs out of memory.
MongoDB requires approximately 1 GB of RAM per 100.000 assets. If the system has to start swapping memory to disk, this will have a severely negative impact on performance and should be avoided.
MongoDB has rapidly gained popularity in the enterprise and the Spring community. While developing and testing Spring Boot applications with MongoDB as the data store, it is common to use the lightweight Embedded MongoDB rather than running a full-fledged server.
You can accomplish this using mongodb-memory-server. The package downloads a mongod binary to your home directory and instantiates a new memory-backed MondoDB instance as needed. For each test file you can spin up a new server which means you can run them all parallel.
For readers using jest and the native mongodb driver, you may find this class useful:
const { MongoClient } = require('mongodb'); const { MongoMemoryServer } = require('mongodb-memory-server'); // Extend the default timeout so MongoDB binaries can download jest.setTimeout(60000); // List your collection names here const COLLECTIONS = []; class DBManager { constructor() { this.db = null; this.server = new MongoMemoryServer(); this.connection = null; } async start() { const url = await this.server.getUri(); this.connection = await MongoClient.connect(url, { useNewUrlParser: true }); this.db = this.connection.db(await this.server.getDbName()); } stop() { this.connection.close(); return this.server.stop(); } cleanup() { return Promise.all(COLLECTIONS.map(c => this.db.collection(c).remove({}))); } } module.exports = DBManager;
Then in each test file you can do the following:
const dbman = new DBManager(); afterAll(() => dbman.stop()); beforeAll(() => dbman.start()); afterEach(() => dbman.cleanup());
I suspect this approach may be similar for other testing frameworks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With