Show some love for Mocha api tests! Setting up #1
In this story I will build simple restful api with
MongoDB. I will set up testing environment with
Docker-Compose and write api tests for all my endpoints without any mocks.
I have been a
Nodejs enthusiast for almost three years already from entry level developer, to junior full stack engineer and now mid level developer. My career mostly consists of full stack development with
Typescript frameworks and libraries like
React. I am also somewhat experienced with
Devops side of software engineering with tools like
Nginx and so on. My current position title is AWS cloud engineer and that’s not only my job but also a hobby as well — mastering AWS cloud.
- NodeJS v12.6.0 or newer;
- NPM v6.14.0 or newer;
- Docker v19.03.13 or newer;
- Docker-compose v1.27.4 or newer;
- Visual Studio Code (or any other code editor of your preference);
Let’s start setting up!
Initialise the project with
npm init command.
jsonschema for body validation.
Scaffold project structure.
Initialise Express application with connection to Mongodb
This is very simple. Great practice is to separate actual express application from web server, hence two separate files were created:
server.js (entry point of the application).
Mongo-connect.js module speaks for itself — it connects to
Mongo database by using mongoose library.
Config.js file will hold all the configuration variables like port, mongo connection string etc, usually these things should come from env variables, but for the purpose of simplicity I will hardcode them. And routes directory — here is the place where our actual api is going to live.
Is something missing?
Mongodb server running on docker. Here is a nice example of docker compose file for
But let me duplicate this file and create another one called
Have you noticed the little difference? That’s right — ports. Development environment will use default 27017 port, but testing environment — 17017. That’s how we can simply ensure that we will have to separate servers for both environments. Also, here is a small update in
Let’s start both of these containers, the commands are almost identical (don’t forget to have docker service running on your machine):
docker-compose up -d — this will launch the development compose file.
docker-compose -f docker-compose-tests.yaml up-d — this will launch the testing compose file.
To bring the services down use the same commands but instead of keyword
up use keyword
You can validate that the containers are running with
docker container ls :
Create a model and register routes
I’m going to create a simple
CRUD api for
Items resource. The item model is going to be very simple:
Notice that I have created
models/Item.js directory and module.
Next up — registering router:
Time for restful api!
Here are five basic crud api endpoints: GET /, GET /:id, POST /, PUT /:id, DELETE /:id.
Now I’m going to do two things — set up
jsonschema validator and install
express-async-wrap to handle all async errors.
Now the easiest part — implementing all http api endpoints.
GET / — very simple api endpoint, it supports two query parameters — size and page and only allows maximum of 100 items to be retrieved at once and defaults to 10. Also, notice the
X-Total-Count header which returns how many items there are in the database.
GET /:id — even smaller api endpoint, but don’t forget to validate incoming id!
POST / — create new item in the database, but this has a key moment — always validate incoming request body. Also, notice
updateItem function — this will explicitly use only wanted fields from DTO (data transfer object). Both schema and updateItem function can and should be reused for PUT /:id endpoint.
PUT /:id has to validate both req.params.id and incoming body.
DELETE /:id — no twists and you got it right — this has to validate req.params.id:
Also, don’t forget to update error handler in
app.js after introducing
We have our api, you can test it via postman, curl or any other tool you prefer. Next story will only consist of api integration tests with no mocks and dedicated Mongodb we have set up. You can find a second part by clicking here.