In memory mongoDB for testing
Tags: node, testing, mongodb
Published: 2020-10-13 13:49:13

This post is originally written here with images and code samples -> https://easyontheweb.com/in-memory-mongodb-for-testing/

When it comes to testing, one of the most fragile places to test is the interaction with the database. Over the years developers have been using mocks to replicate what their database would ideally behave as and use those mocks in their tests to test the functionality that they are testing. Mocks are great ! I like them too to an extent but I also felt that mocking functions does not give me the same level of confidence that an actual database call would. In comes in-memory mongoDB for testing.

Then, one day I found a great package called mongodb-memory-server and I think it’s really good as it uses an in-memory MongoDB for testing. Now, what does that mean and how we can use the above mentioned module for testing code in our application ? We’ll cover both these things in this article but let’s first discuss on why an actual db call is what I prefer to test my code over mocks.

Why an in-memory database for testing ?
Assume you are writing code that heavily relies on making database queries, writing and updating the database and all sorts of different things related to your DB. To test this piece of code you begin by writing the business logic and then proceed to write the tests for the database interactions. Now, what I did earlier and what many people do (even me at times) is write a mock function that will just replicate the behaviour that the database is expected to do for that particular action on it.

Mocks are good that they do not actually need a real database and you can just ‘mock’ it and not much hardware is used to run them (they are just blocks of simple code that you have written yourself). But, there is an issue with mocks – well, you write them yourself ! So ? Well, if you write them yourself no matter how precise a code you write you might make a mistake in replicating your database’s behaviour.

Being fully confident in your mock function is not possible according to me. No matter how closely you try replicating it, it is not a real database function and well, as I said the level of confidence you’ll get using that mock is not very high.

In come in-memory databases. What are in-memory databases ? In-memory databases are databases that do not actual touch your hard-drive and are spun up, run and then closed in your main memory itself. They are faster than regular ones because they do not actually make any changes to the disk and are well suited for testing as they are destroyed instantly.

Let us see the advantages and disadvantages of in memory databases next.

Advantages and disadvantages of in-memory databases
Advantages of using in memory database for testing :-

Faster development time as you do not need to create mocks for every query.
More reliable tests as you eradicate the possibility of human error while writing mocks.
Closer to the actual application as you are really working with a database.
Disadvantages of using in memory databases for testing :-

The database needs seeding (filling up with data).
Tests take longer to run as they are actually interacting with a database.
More memory usage
Now that I’ve listed both the pros and cons for in memory databases it’s upto you whether you want to use them for your tests or would you prefer writing mocks, that’s totally a personal choice.

In the next section, let us use the npm package mongodb-memory-server to test our node code and see how easy it is to set up and use !

Testing nodeJS with mongodb-memory-server
1
npm i --save-dev jest supertest mongodb-memory-server @types/jest @tyeps/supertest ts-jest
Note that you only need to install the first three packages if you are working with Javascript rather than Typescript.

You see that we are using jest as our testing library of choice and it is one that I highly recommend. So, in your package.json file make the following changes :-


Here also, no need to set the preset in “jest” if you are not using typescript. (We installed ts-jest in the last command).

The setupFilesAfterEnv is a very important property for us because it lets us define a file that will be run to setup our testing environment for jest. As you can see we call this file setup.ts and this is where we’ll be working and setting up our in memory-database.


In this file, we use three test lifecycle methods of beforeAll(runs once before all the tests), beforeEach(runs once before every test) and afterAll(runs after completion of all the tests).

What we see is that we spin up a new in memory mongo database in the line mongo = new MongoMemoryServer and then connect it to our mongoose ODM layer using a connection string just like we do our real database. The difference here is that this in-memory one will be connected to our mongoose only in a testing environment.

The beforeEach and afterAll functions are also quite self-explanatory but you can leave a comment down if you did not get what they are supposed to be doing.

Let us see how you can easily test some piece of code that expects a mongo doc back or involves any sort of database operation :-


Yep ! No more mocks, just a simple API call that will be taken care of itself by the in-memory database we just spun up.

There are a whole lot of configuration options for you to explore with this package here -> https://github.com/nodkz/mongodb-memory-server

This is it for this article on using in memory-databases for testing your applications. I hope you found the stuff in this article interesting and you’ll be taking a look at using this in one of your projects and trying it out if this is suitable for you or not.

If you want to read my other articles on MongoDB please check out this link here -> https://easyontheweb.com/category/mongo/ .

Also, if you want to join a facebook group with other web developers and bloggers including me please join here -> https://www.facebook.com/groups/503230450489995