Data driven NodeJS tutorials Part 1 - Basic server with test

Hi all,

I'm writing a brief series about using NodeJS in a purely data-driven fashion - for those who like to keep their backends and front-ends distinct, this series should provide a quick kickstart.

I'm pushing the code from each tutorial into this public git repo:

https://github.com/philhudson91/data-driven-nodejs-tutorials

Let's get going!

Step 1 - Set up

Before doing these tutorials, we'll need to make sure you have a few things installed; namely NodeJS.

To check if NodeJS is installed, fire up a terminal and run the following command:

which node

If it responds with a path to Node (something like /usr/local/bin/node) then things will be okay. If not, you can easily install node here.

Step 2 - Packages/dependencies and NPM

Node comes with a built in package manager - NPM (Node Package Manager).

For this basic app, we will require some packages to be installed (otherwise referred to as the app's dependencies).

NPM uses a JSON file to describe the dependencies of the application. Let's create this below:

package.json

{
  "name": "application-name",
  "version": "0.0.1",
  "dependencies": {
    "body-parser": "^1.0.2",
    "express": "^4.0.0",
    "request": "^2.67.0"
  },
  "devDependencies": {
    "chai": "^1.9.1",
    "chance": "^0.5.9",
    "mocha": "^1.18.2",
    "node-inspector": "^0.12.3",
    "supertest": "^0.13.0"
  }
}

As you can see the file is strict to JSON standards, NPM will not parse it otherwise.

It has two main blocks:

  1. dependencies - The dependencies for running out application.

  2. devDependencies - Dependencies only required for developing our application.

To briefly explain the dependencies we have - our dependencies block requires the minimum to run our server - most importantly express. Our devDependencies block includes modules to allow us to test the code that we are writing.

Step 3 - Install the dependencies

Using terminal, ensure you are in the project directory. If not, run:

cd path/to/code (or wherever your working directory is)

Now to install the dependencies run:

npm install

Node Package Manager will now look for the package.json file, parse it and install everything from the file into a node_modules folder.

Step 4 - Writing the basic server

Let's get cracking on making something that works.

We will now create the main application file, which is used to start and run the application as well as include some basic configuration.

Create the files app.js and route.js with the code below. I will run through what this code means now.

app.js

#!/usr/bin/env node

//imports
var express = require('express');
var bodyParser = require('body-parser');
var routes = require('./routes.js');

//instantiate express
var app = express();

//config
app.use(bodyParser.json({}));

//use routes to map URLs to handlers
app.use('/', routes);

//catch 404 and forwarding to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
}); 

//set the application port
app.set('port', 3000);

//set the server
var server = app.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + server.address().port);
});

routes.js

var express = require('express');
var router = express.Router();

/* Map URLs to handlers in this file */

router.get('/', function (req, res) {
    res.status(200).json({message: "ok"});
});

module.exports = router;

What have we done here? Let's run through the code in more detail:

app.js:

#!/usr/bin/env node

Here we set the path to NodeJS, so that our application can be run using the node app.js command.

//imports
var express = require('express');
var bodyParser = require('body-parser');
var routes = require('./routes.js');

Here we import the dependencies that for our application - these are what we installed with NPM and the routes.js files that we just created. These are now variables within our app.js file and can be accessed like usual JavaScript variables.

//instantiate express
var app = express();

//config
app.use(bodyParser.json({}));

//use routes to map URLs to handlers
app.use('/', routes);

This bit is pretty standard - we instantiate express to our app variable. We specify our app variable to use bodyParser and our routes file.

//catch 404 and forwarding to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
}); 

Now if the route that is attempted to be access is not present in our routes file, we will simply throw a 404.

//set the application port
app.set('port', 3000);

Here we set the application port - in later editions we will do this using environment variables, but for this first tutorial keeping it simple is best!

//set the server
var server = app.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + server.address().port);
});

Now we instantiate the server and set the app to listen on the port previously specified. When the app is started, it will console.log() that it's started and on which port.

Now for our routes.js file.

var express = require('express');
var router = express.Router();

Like in app.js, we have imported modules that we require - express and our router.

router.get('/', function (req, res) {
    res.status(200).json({message: "ok"});
});

Now we map the path / to a function with two parameters, req and res. When working with Node you'll encounter these a lot. Req refers to 'request' and res refers to 'response'.

So when this path is accessed it triggers a function return the response status of 200, with a JSON message of "ok".

module.exports = router;

When then export the router as a module so it is accessible from global scope and can be imported into other parts of our application if required.

Step 5 - Run the application

Now let's see if it works.

Head into terminal and run:

node app.js

You should see a message like:

Express server listening on port 3000

Now head to an internet browser and go to: localhost:3000. You should see the JSON message from the server saying 'OK'.

If so it works! Yay!

But now with all code, we need to ensure that it has some tests. Let's write these in the next step.

Step 6 - Writing a basic test

Writing tests for your code seems like a bit of a drag at first, it takes time. But, it will save you much more time in the future when your codebase starts to expand, refactors are required and you need to have a suite to check if everything still works as expected in your application.

So let's write this now.

Create the directory and file: tests/test.js

test.js:

var expect = require('chai').expect;
var supertest = require('supertest');
var api = supertest('http://localhost:3000');

describe('get main endpoint', function () {

    it('responds with 200', function (done) {

        api.get('/')
            .expect(200)
            .end(function (err, res) {

                if (err) {
                    return done(err);
                }

                done();

            });
    });

});

Let's explain what this does now:

var expect = require('chai').expect;
var supertest = require('supertest');
var api = supertest('http://localhost:3000');

Once again we have our imports - the modules we will use for our test. Expect is a sub-module of Chai, and allows us to declare what we expect will happen for a certain action and supertest allows us to interact with an api (that we have specified is at localhost:3000).

describe('get main endpoint', function () {

    it('responds with 200', function (done) {

        api.get('/')
            .expect(200)
            .end(function (err, res) {

                if (err) {
                    return done(err);
                }

                done();

            });
    });

});

Now the main bulk of our test - we describe what it will test - it will test getting the main endpoint.

We state what it should do - it should respond with a 200.

Now we use supertest to make the request, and Chai for the expect status. If the expect returns true, there will not be any error and the test will pass. Otherwise, it will return false and the test will fail.

Now let's run the test using:

mocha

If all is well, the test should pass and you should see the following output in the terminal.

 get main endpoint
    ✓ responds with 200

 1 passing (36ms)

Yay!

Summary

This basic tutorial demonstrates how to create a basic Express server, with modularised routes and a basic test using Supertest, Mocha and Chai.

I'll be creating more of these tutorials so please check. If you have any questions let me know.

Once again, you can find the code here:

https://github.com/philhudson91/data-driven-nodejs-tutorials

Phil Hudson

Read more posts by this author.