“Test-driven development (TDD) is a way of managing fear during programming” — Kent Beck

Introduction

TDD which stands for test driven development is a way of building software applications. This approach adds extra complexity to the process. Developer has to write extra code — test cases. TDD makes sure that the piece of code is doing the required task before releasing. It makes sure the code can be changed easily as business requirement tends to change. The process consists of three main steps: Writing failing tests, writing code that satisfies tests and refactoring.

Before Start

  • The application code should meet certain standards then it can be tested.
  • The application uses MVC architecture.
  • This tutorial only focuses on testing the controllers [business logic].

Setup Environment

mkdir todo-api
npm init -y

Install Dependencies

Dependencies:

npm i -S express body-parser mysql2 sequelize morgan

npm i -D chai mocha nodemon sinon

File Structure

The file structure of a typical Node.js MVC app goes like bellow:

Image for post

Node.js API File Structure

The test files for controllers reside in controllers folder and prefixed with **.spec.js_. This is just a _personal preference**.

Test Command

The test command is inside the package.json file as:

“test”: “mocha controllers/*.spec.js”

Writing Failing Test

The first step in TDD is writing the failing tests. The requirements are gathered and test cases are written for them. Before writing the test cases, the requirement should be clear.

Requirement Document

Todo is simple text that informs a piece of work to be done. The Todo application allows the user to **create todos **and list all todos.

Based on the requirement there should be two APIs — create todo and list todos.

Test Cases

Here are the list of test cases:

describe('todoController', function() {
  describe('createTodo', function() {
    it('text should be provided');
    it('should send success result if todo is saved to database');
    it('should send fail result if todo is not saved to database');
  });

  describe('fetchTodos', function() {
    it('should send a list of todos with success message');
    it('should send fail result if todo is not fetched from database');
  });
});

Now if the command npm test is run, mocha shows the bellow. There are five pending with no passing or failing tests.

Image for post

  • Import chai, sinon and todoController.
  • Restore** sinon** as per their documentation after each test.
  • Before each test, declare req, **res **and **next **using **faking **or stubing. They are needed to be sent as arguments to the controllers.
const chai = require('chai');
const sinon = require('sinon');
const expect = chai.expect;
const {createTodo, listTodos} = require('./todoController');

describe('todoController', function() {

    beforeEach(function() {
        req = {body: {text: 'Go to the meeting!'}, db: {TodoModel: {create: null, findAll: null}}};
        res = {json: sinon.fake()};
        next = sinon.fake();
    });

    afterEach(function() {
        sinon.restore();
    });

    describe('createTodo', function() {
        it('text should be provided');
        it('should send success result if todo is saved to database');
        it('should send fail result if todo is not saved to database');
    });

    describe('fetchTodos', function() {
        it('should send a list of todos with success message');
        it('should send fail result if todo is not fetched from database');
    });
});

#javascript #node #testing #api #developer

Test Driven Development - Node.js API 
1.75 GEEK