How To Write An Express JS Server Using Test Driven Development

Part One: Setting Up Environments

Mbuyu Makayi
Feb 10, 2019 · 9 min read
Image for post
Image for post
courtesy of freecodecamp

Why TDD In First Place?

It is time for that presentation, you get through the initial parts of the application well, until it’s time to show off the upload feature you just implemented — then boom! It is not working anymore. You try again — boom nothing, you start panicking at this point. You begin to dread being a programmer, you probably tell your boss or professor that it was working, you even swear on it.

This is where Test Driven Development comes to the rescue. It is the practice of writing tests that test that your code is doing what is supposed to do. In this practice, you write tests before you wrote the actual code. For example, if you have a function that calculates the sum of two number and returns it, you will write a test that checks that the returned sum is the expected one.

Now you probably wondering how can we test a function that is not written yet and won’t that test fail? Yes, it is supposed to initially fail. Your test has to fail until you write the function that returns the correct sum when two numbers are provided. The benefit is that those test will always check to see that in case you make some changes to your code, you have an intermediate way of knowing whether those changes haven’t broken something. For more reading on the topic here a brilliant article from freeCodeCamp:

What are we building?

We are going to build a small server that provides APIs for most popular movies, searching for movies and some other CRUD functions.

What do we need?

  1. Config— Helps setting up environments (development, test, and production).
  2. Debug — Only show logs in test or development environments.
  3. Mongoose — An elegant ODM for MongoDB in Node JS.
  4. Mocha — Testing framework.
  5. Nodemon — Restarts our development server automatically.
  6. Chai — Our TDD/BDD assertion library.
  7. Babel CLI — A Javascript compiler.
  8. SuperTest — HTTP server testing library.
  9. Yarn — Fast, Reliable, & Secure Dependency Manager ( you are free to use npm instead, just replace the commands with npm equivalent)

Setting Up Stuff

1. mkdir movie_server ; cd movie_server2. yarn init3. yarn add  mocha chai debug supertest nodemon babel-cli babel-preset-node8 config --dev4. yarn add express mongoose 5. mkdir dist //when you run yarn build,prod files will be stored here 6. mkdir tests // mocha will look for tests here.
7. mkdir src ; cd src ; touch index.js &

After you run these commands you will then go to your package.json and set up your scripts like this:

"build": "babel src -d dist --source-maps"

So the first script setups up what happens when you run yarn run build. Here we are using babel to compile all the code in the src folder and convert it to ES5 syntax and store it in the dist folder. In our production setup, our application will be running from this folder.

"serve":"NODE_ENV=production node dist/index.js",

The second script line starts the server in the production environment or mode by setting the environmental variable NODE_ENV to production. This is important because they are certain lines of code that you only want to run in production or there are certain configurations that you only want to make available in production mode. This should only be run after running yarn run build. Notice that we are not using Babel just node, this is because the code is already compiled to a version that node without any special compilers like babel using the build command.

"dev":"DEBUG=server:debug NODE_ENV=development nodemon src/index.js --exec babel-node"

This line will start the application in development mode and here we are using nodemon to make sure that whenever we change our code, the node server is able to restart and load the new changes. We also set up an environmental variable called DEBUG which we set to server:debug, this is need by the package Debug to determine whether to show console logs or not depending on the environment. Here we only want to show logs when we are running in the application in debug mode. I will explain how we do this as we go on. We also set the script to execute using babel-node, this allows us to use the latest javascript syntax ES6+.

"test":"DEBUG=server:debug NODE_ENV=test mocha --require babel-core/register --reporter spec --exit   tests/ "

Lastly, we set up the script for running tests. Here our environment is set to test, we also set it to run our tests using Mocha. We make sure that we instruct mocha to babel-core/register, this is important for our ES6+ code syntax to run, without it, mocha will fail to do so. Also, we set up the reporter flag to use spec which defines how our tests will look like in our console. We also use the exit flag which commands mocha to stop its process when all the tests are done else it will hang. Last we tell Mocha to look for tests in the tests folder.

Let’s Setup Our Environments Using Config

To set up our config files, create a folder called configs and create three files namely: development.json, test.json, and production.json ( it is important that you name these files the same names your NODE_ENV environmental variable is holding in each of the scripts in pacakge.json). Each file should contain a JSON Object with whatever keys/value pair you wish to use. I use the name, database, and port as my keys.

// configs/development.json
{
"name": "Server Developement","database": "mongodb://localhost:27017/development","port": 3000}// configs/test.json
{
"name": "Server Test","database": "mongodb://localhost:27017/test","port": 3100}// configs/production.json
{
"name": "Server Production","database": "mongodb://localhost:27017/production","port": 3000}

Testing The Environments

Development Mode

Let’s now test that our server is running and it does so in the right environment depending on the command we use to start it. Here we testing that it is running the development environment using the following command.

yarn run dev
Image for post
Image for post

You can see that our server is running on the appropriate port set in the development.json file in the configs folder and that is running server development mode.

Test Mode

yarn run test
Image for post
Image for post

Notice that is says 0 passing. Why is that? Well, this is okay, it means that Mocha is working but just didn’t find any tests and that we are running in the test environment. So we can then write tests for Mocha to run. Our first test will just check that the server is running on the port specified in the respective JSON config file being used.

In the code above, we import expect method from chai, this method allows us to make assertions about the server. In this case, we want to test that the port the server is running on, is the same as the one used in the test.json file in the config folder. We wrap our test in describe function (takes in the name and callback function) which is just used to group similar tests. The actual test is in ‘it’ function (also takes description and callback as well). The test reads like plain english: expect server.port to equal the port number in the current environments config file.

Image for post
Image for post

After this rerun yarn run test and you can see that the server is running in test mode and that the test passes. If you change the port number in the app.listen() method in index.js and rerun the tests, you see it fail and you will immediately know that something is wrong.

Image for post
Image for post

Production Mode

yarn run build
Image for post
Image for post

After running yarn run build, you see that the dist folder has new files. These files are generated so you shouldn’t make any changes to them. If you make changes to your code, just regenerate them using the same command. At this point, you can now run yarn run serve.

yarn run serve
Image for post
Image for post

Notice that there is no console output showing which port the server is running on, this is because in the serve script we haven’t set DEBUG=server:debug cause we don’t want to show logs when running the application in production mode. The rule is not you should never show logs in production mode, especially error logs, as they might contain sensitive information. But since it is necessary to know which port, the server is running on, you can add this line:

console.log(`server is running on port ${config.get('port')} and in ${config.get('name')} mode`);

Stop the server using ctrl +d run yarn run build and then run yarn run serve and you will see the following message.

Image for post
Image for post

Conclusion

The code for this tutorial can be found here: https://github.com/makayi/express-tdd-tutorial

Thanks for reading and happy coding.

UPDATE: part two is out

Developer Circle Lusaka

This is the official medium Publication for Developer…

Thanks to Olivier J.M

Mbuyu Makayi

Written by

Senior Software Engineer at The ZIG| Facebook Developer Circle:Lusaka Community Lead | Amateur Photographer | Fullstack Javascript

Developer Circle Lusaka

This is the official medium Publication for Developer Circles Lusaka

Mbuyu Makayi

Written by

Senior Software Engineer at The ZIG| Facebook Developer Circle:Lusaka Community Lead | Amateur Photographer | Fullstack Javascript

Developer Circle Lusaka

This is the official medium Publication for Developer Circles Lusaka

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store