Node.js has become a popular choice for backend. Frameworks like Express make it easy to quickly build a powerful API. If you provide a (public) API then you want to make sure code changes do not break your API. One way to ensure this is to write tests which are executed regularly (e.g. before merging a pull request).

We will use the following technologies:

SuperTest to call our API routes since it provides an easy-to-use API to send HTTP requests in Node

to call our API routes since it provides an easy-to-use API to send HTTP requests in Node Jest as testing framework since it provides a great testing experience for JavaScript projects

as testing framework since it provides a great testing experience for JavaScript projects TypeScript (optional) since it greatly improves developer productivity

How to write API tests in JavaScript / TypeScript

Install the necessary dependencies: npm install jest supertest @types/jest @types/supertest ts-jest --save=dev . The types and ts-jest are not required but recommended if you use TypeScript. You can also install Jest globally using the -g flag. Create a Jest configuration either in a separate file (recommended) or in your package.json. Create a folder containing your spec files (e.g. tests) which Jest should run. Write your tests using Jest & SuperTest. You should name your test files consistently (e.g. user-routes.spec.ts). Run your tests using Jest: jest to run them once or jest --watchAll to enable watch mode. Optional: measure the test coverage by using the --coverage flag. To ensure that the test coverage only goes up and does not decrease over time we can set up thresholds. If thresholds are not met then Jest will fail. You can configure thresholds for directories, file types and even individual files by customizing the coverageThreshold in your Jest configuration. Optional: create a globalSetup and a globalTeardown file which will be executed once before/after all tests are executed respectively. The idea is to execute heavy work & cleanup once. Use cases: create a database / user / authorization & delete everything which has been created during tests execution in the end. Optional: install TypeScript with the command npm install typescript --save=dev . TypeScript is a great choice for modern JavaScript projects as it provides type-safety and allows developers to use modern features even in older browsers. If you have a Java or C# background, then TypeScript will be more pleasing to use.

Here is a sample Jest configuration in a separate file:

module.exports = {

// preset: 'ts-jest', // use this if you are using TypeScript

globalSetup: './jest.global-setup.js', // optional: will be called once before all tests are executed

// globalTeardown: './jest.global-teardown.js', // optional: will be called once after all tests are executed

coverageThreshold: {

global: {

branches: 80,

functions: 80,

lines: 80,

statements: 80

}

} // optional: let Jest fail if thresholds are not met

};

Here is a sample SuperAgent spec which is testing the login feature:

import request from 'supertest';

const app = require('../app'); // our Node application describe('Login', () => { it('succeeds with correct credentials', async () => {

const response = await post(`login`, demoUser)

.expect(200);

expect(res.body.user.email).toBe(demoUser.email);

}); it('fails with invalid credentials', async () => {

const user = {email:'notarealmail@mycompany.com', password: 'somepassword'};

await post(`login`, user)

.expect(401);

}); it('fails with missing credentials', async () => {

const user = {};

await post(`login`, user)

.expect(401);

}); });

export function post(url, body){

const httpRequest = request(app).post(url);

httpRequest.send(body);

httpRequest.set('Accept', 'application/json')

httpRequest.set('Origin', '

return httpRequest;

} // a helper function to make a POST request.export function post(url, body){const httpRequest = request(app).post(url);httpRequest.send(body);httpRequest.set('Accept', 'application/json')httpRequest.set('Origin', ' http://localhost:3000' return httpRequest;

And here is a sample globalSetup file (globalTeardown works the same way). In this case, I am creating a new database with MongoDB to be used in my API tests. As you can see, an async function is exported.

/**

* Connect to the test database (and create if it does not exist yet).

* Creates all necessary MongoDB collections.

*/

export default async () => {

const collections = ['user', 'company', ...];

const dbManager = await getDemoDB();

for (let collection of collections) {

await dbManager.db.createCollection(collection);

}

await prepareDatabase();

}

How to disable concurrency (parallel execution) in Jest

By default, Jest will detect how many tests it should run concurrently. This should speed up testing since tests can run in parallel. However, this might be a problem if your tests depend on each other or if you want to have more stable results. In this case, you can use the --runInBand option to make Jest run tests sequentially.

Run Jest tests using your IDE (IntelliJ, Visual Studio Code)

Jetbrains (the maker of IntelliJ IDEA/WebStorm…) has created a Jest plugin which allows you to run tests directly from your IDE. If you are using Visual Studio Code, you can easily create a launch configuration which you can execute from inside it. All you need to do is to create a launch.json file in your .vscode folder in your repository and add the following configurations:

{

"type": "node",

"request": "launch",

"name": "Jest: Run all",

"program": "${workspaceFolder}/node_modules/.bin/jest",

"args": [],

"console": "integratedTerminal",

"internalConsoleOptions": "neverOpen",

"disableOptimisticBPs": true

},

{

"type": "node",

"request": "launch",

"name": "Jest: Run current File",

"program": "${workspaceFolder}/node_modules/.bin/jest",

"args": [

"${relativeFile}"

],

"console": "integratedTerminal",

"internalConsoleOptions": "neverOpen",

"disableOptimisticBPs": true

}

}

Conclusion

Thanks for reading this article. As you can see, it is easy to write API tests in JavaScript. As I mentioned in my post about using Jest in Angular projects, Jest once again demonstrates that it can be used in any kind of JavaScript project. TypeScript helps making code more clean and identify issues more quickly through static typing. And SuperTest allows us to easily make HTTP requests in tests. What do you use for writing API tests for Node.js? Let me know in the comments.