Testing Controllers In NestJS + Mongo With Jest

Methods to plan and write stable unit exams with Jest to your NestJS controllers when utilizing MongoDB and Mongoose

Image with Jest, NestJS and MongoDB logo

On this article, you’ll be taught, by instance, easy methods to plan and write stable unit exams with Jest to your NestJS controllers when utilizing MongoDB and Mongoose. Many of the testing strategies used right here might be utilized with out NestJS, utilizing different DBMS (Database Administration System) and even utilizing a testing library apart from Jest! These are getting used right here as a consequence of their relevance and due to how a lot work they simplify.

Earlier than leaping into the code, lets see a fast overview of the primary libraries used (set up them with NPM).

A Node.js framework for writing server-side purposes with JavaScript or, higher but, TypeScript. NestJS simplifies the architectural a part of the event by offering its personal out-of-the-box utility architectural patterns, aimed to offer scalability, decoupling, straightforward upkeep, and, in fact, testability. The NestJS core weekly downloads at NPM have been growing persistently, with greater than 1.3 million of downloads within the final week.

Graph showing the increase of weekly downloads

I used “mongo” to reffer to MongoDB + Mongoose + MongoDB Memory Server. MongoDB is a performant NoSQL DBMS that shops knowledge as JSON-like formatted paperwork. Mongoose is a JavaScript object modeling library that makes interacting with MongoDB simpler and safer. MongoDB Reminiscence Server is a library that spins up an precise/actual MongoDB server programmatically from inside Node.js.

Jest is an entire JavaScript testing framework developed by Meta (beforehand Fb) with give attention to simplicity and efficiency (exams run in parallel, for instance). The Jest weekly downloads at NPM has been growing persistently, with greater than 17.3 million of downloads within the final week.

Graph showing the increase of weekly downloads

What will we need to implement and take a look at on this information? We are going to implement and take a look at two endpoints in a NestJS controller. A GET endpoint mapped to a way referred to as getArticle and a POST endpoint mapped to a way referred to as postArticle.

The codes and venture construction used listed below are simplified to give attention to the testing features. If you wish to see extra exams and code in a extra full venture context, consult with the next GitHub repository:

This was a problem from Coodesh. Merely put, the aim is to make an API able to interfacing CRUD (Create, Learn, Replace and Delete) operations on a database of area flight information articles.

How would you begin to write your code and the exams? If you have already got your code achieved, good! You’ll be able to write your exams. However I want to shortly discuss a great observe know as Check Pushed Growth (TDD).

In TDD, we observe these three guidelines:

1- You shouldn’t write any manufacturing code earlier than writing an unit take a look at that ensures the proper conduct.

2- You shouldn’t write extra exams than sufficient to the failure.

3- You shouldn’t write extra manufacturing code than sufficient to cross the take a look at.

These guidelines lead us to the next workflow:

Blocks with descriptions linked in the following order: TDD, Write Test, Write Code That Passes The Test and Refactor. The “Refactor” block has a dotted line pointing back to “Write Test”.
TDD workflow

First, we write the exams that guarantee the proper conduct of the algorithm we need to implement (“with the X enter, the exception, error, or end result anticipated is Y”). Then, we write simply sufficient code to cross the exams. Lastly, once we enhance our code, we return to step one and a cycle is created.

Instantly answering the query within the matter, we’ll begin from the exams.

The significance of this half can’t be overstated. If we plan our exams incorrect, our code may even be incorrect, thus making us waste effort and time.

The exams ought to mirror the necessities for the characteristic/performance you are attempting to implement. One other particular person should be capable of know what your code takes as enter, what it provides as output and when and the way it will fail. The take a look at is the most effective documentation doable to your code.

Our postArticle technique should obtain an article as parameter and return the saved model of the article or an exception, in case one other article with the identical title is already saved. The getArticle technique should obtain a title as parameter and return the article with the corresponding title or null. These are the behaviors we’re going to take a look at.

Observe: Right here we’re going to use the title of the article (string) as an identifier, however a much better concept is to make use of the personal database id (often a constructive integer).

The Controller, Module and Service

To begin from the scratch, your controller, module, and repair recordsdata ought to seem like the next:

NestJS could already put some easy strategies in your controller and repair recordsdata while you create them utilizing the Nest CLI, however take away them and their dependencies if that’s the case.

The Article

We need to save articles to our database, however what precisely is an article? We should outline the construction of an article.

Since we additionally need to persist (save) the articles in our MongoDB database, we should create the corresponding MongoDB schema.

The Stubs

When testing, we use “stubs”. These are situations, with predefined values, of the objects that we’re going to use when testing. It’s a good observe to create a folder referred to as “take a look at” within the root of your venture with a subfolder referred to as “stubs” and save your stubs there.

Since we’ll want an occasion of an article to check our code, lets make an article stub.

Discover that we’re exporting an occasion of the ArticleDTO referred to as ArticleSTOStub with predefined values.

The Exception

We need to return an exception when somebody tries to save lots of an article with a repeated title, so lets write this exception.

We named it ArticleAlreadyExists, outlined a customized error message (“Article already exists!”) and set the HTTP response code to 400 (Unhealthy Request).

The Database Connection

To setup the reference to the database, we may do one thing like this in our controller:

Mainly, we used the MongooseModule to cross our schema with the forFeature technique and the MongoDB connection URI with the forRoot technique. Observe that right here we’re passing our connection URI by an surroundings variable to keep away from exposing it as a string in our code.

The Base for a Check File

First, lets create our take a look at file. If NestJS already created one for you, delete it and observe together with us. In case of unit exams, create the take a look at file in the identical folder because the file with the code to be examined and title it by appending the .spec suffix within the title of the file with the code to be examined. Jest additionally expects these conventions by default. So, if the controller is named app.controller.ts, the take a look at file might be referred to as app.controller.spec.ts and ought to be in the identical folder.

With the file created, lets begin writing some code.

Line 1: We imported a category referred to as Check and a kind referred to as TestingModule from @nestjs/testing.

Line 2: We imported the controller we need to take a look at.

Line 3: We imported the service that our controller makes use of/relies upon.

Line 6: The describe from Jest creates a block of exams and allows you to cross a string as parameter in an effort to point out their normal objective. Since we need to take a look at our AppController, lets simply write it.

Line 7: Quickly, we’ll instantiate our controller in an effort to entry its strategies (postArticle and getArticle), however lets declare it right here within the international scope of this block in order that we will consult with our controller inside any take a look at (since every take a look at might be a perform contained in the block with its personal scope).

Line 9: The beforeAll from Jest creates a block of code that might be run earlier than any of the exams.

Line 10–15: We compile our utility (app) passing the controller we need to take a look at and the suppliers it wants.

Line 16: From our compiled app, we get the occasion of the controller we’d like (appController).

If you happen to write jest in your terminal and press enter to run, you will note an error, however for those who learn rigorously (all the time take note of the error messages), you will see that what the issue is: Your take a look at suite should include a minimum of one take a look at.

We did lay some foundations, however we nonetheless haven’t written any take a look at.

The Database Connection Drawback

We don’t need to mess with our manufacturing database when testing. You’ll be able to take into consideration organising a distant take a look at database, however that additionally has a number of issues corresponding to schema buildings mismatches, the lack to check offline and the dearth of management over the state of the database when a number of individuals are utilizing it.

Essentially the most used strategy is “mocking” the interactions with the database, that’s, setting predefined responses to the strategies concerned within the retrieval or alteration of knowledge with out actually relying in any type of database occasion.

This technique, nonetheless, often turns into complicated shortly and provides yet another layer of artificiality in your exams. A greater strategy is to run an on-demand and devoted occasion of the database in you RAM for testing. That’s what we’re going to do with MongoDBMemoryServer.

Line 17: We create a brand new MongoDB server and get the daemon (mongod)

Line 18: We get the connection URI for the MongoDB server we simply began

Line 19: We join and get the connection to the MongoDB server utilizing the URI

Line 20: Via the connection, we get the mannequin of the schema we need to manipulate (Article)

Line 25: We offer our Article schema mannequin, akin to what we did beforehand within the app.module.ts. The distinction right here is simply that this mannequin is from our short-term RAM database, and never from our actual database specified by the MONGODB_CONNECTION_URI surroundings variable.

Now, lets add two extra blocks from Jest, the afterAll and afterEach.

Line 31–35: Right here, we’re saying that in spite of everything our exams have run, we’ve to drop (delete) the database, shut the connection and cease the daemon.

Line 37–43: Now, we’re saying that after every particular person take a look at, we’re going to delete all entries (paperwork/knowledge) from our collections. On this case, we solely have one assortment (for the articles), however it’s a good observe to make it extra generalist. The thought is to all the time begin a take a look at with a clear database.

Testing postArticle

Now, we’re lastly capable of write a batch of exams for the postArticle technique. Simply to recollect, this technique should obtain an article as parameter and return the saved model of the article or an exception, in case one other article with the identical title is already saved.

To create a batch of exams, we use a describe block from Jest with a number of it blocks. An it block corresponds to at least one particular take a look at situation and may name the count on perform at its finish to test the situation that validates the take a look at.

Based mostly on our necessities, we will assume in 2 easy take a look at situations.

1 — The article is legitimate and ought to be saved with none drawback.

2 — The article title is repeated and an exception ought to be thrown.

We are going to write one describe block for the postArticle technique with two it blocks, one for every one of many exams.

Line 49: We cross our article stub to the postArticle technique and get the returned created article.

Line 50: We use the count on perform to test if the title of the created article is the same as the title of the article we handed to be saved. ThetoBe technique specifies the logical comparability we need to carry out. There are a number of completely different strategies for quite a lot of checks. If this expression returns something apart from true, the take a look at is taken into account failed.

Line 53: Right here, we save our article stub within the database utilizing mongoose (discover that we’re utilizing the articleModel). We may use our postArticle technique to save lots of the article stub, however the technique may include extra logic than a easy save, thus introducing extra uncertainties once we merely need to put one thing within the database.

Line 54–56: Right here, we use the postArticle technique and attempt to save an article that already exists within the database, since we saved it within the line above, and test to see if the anticipated exception might be thrown. The rejects technique is used while you need to cope with rejected guarantees and the toThrow technique checks if the error is an occasion of ArticleAlreadyExists.

Do not forget that postArticle nonetheless doesn’t exist, so your IDE may warn you about that and for those who attempt to run the take a look at file, additionally, you will get errors associated to that. Nonetheless, notice that now we already know the way the strategy should behave and we’ve a simple option to test that and present to others.

Testing getArticle

The getArticle technique should obtain a title as parameter and return the article with the corresponding title or return null.

Based mostly on our necessities, we will assume in 2 easy take a look at situations.

1 — The article with the corresponding title is discovered and returned.

2 — There is no such thing as a article with the corresponding title and null ought to be returned.

Let’s write the exams.

Line 62: Once more, it is very important not use the postArticle technique right here to save lots of the article. If you happen to used it right here and an error occurred within the postArticle technique, the take a look at would say that an error occurred when testing getArticle, making issues extra complicated. All the time attempt to isolate what you might be testing.

Line 63: Right here we use getArticle to seek for the title of the article we beforehand saved and retailer the return.

Line 64: Now, we test if the title of the article discovered and returned is the same as the one of many article we saved.

Line 67: With out beforehand saving something to the database (keep in mind that the afterEach technique clears the database after every take a look at), we attempt to discover an article by its title.

Line 68: We use toBeNull to test if the article article is null, as anticipated.

Now that the exams are achieved, we should always write simply sufficient code to cross them, since passing the exams implies that the functionalities are full and correct.

The main target of the article was the exams, so there is not going to be a lot rationalization concerning the implementation of the strategies itself.

Now, while you execute npm take a look at within the terminal, all exams ought to run and cross with out issues.

Result of the “npm test” command in the terminal showing that all the 4 tests passed with success

To see the take a look at protection, use npm run take a look at:cov. The take a look at protection end result reveals how a lot of your code is examined by all of your exams and is an efficient metric for code high quality.

Result of the “npm run test:cov” command in the terminal showing percentages related to the code coverage of the tests

As a way to make your exams run routinely everytime you make adjustments to your code, use npm run take a look at:watch. There are additionally some helpful VS Code extensions that can assist you monitoring your exams execution, such because the “Jest” extension from “Orta”.

More Posts