← Back to Tutorials Chapter 9

Testing & Debugging

Debugging Techniques

Node.js provides several built-in debugging options:

Console Debugging

// Basic console logging
console.log('Debug value:', variable);
console.error('Error:', error);
console.warn('Warning:', warning);
console.table([{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]);

// Console groups
console.group('User Details');
console.log('Name: Alice');
console.log('Age: 30');
console.groupEnd();

Using the Built-in Inspector

# Start with inspector
node --inspect app.js

# Pause at start
node --inspect-brk app.js

# Open chrome://inspect in Chrome to debug

Using debugger statement

function calculateTotal(items) {
  let total = 0;
  for (const item of items) {
    debugger;  // Execution pauses here
    total += item.price * item.quantity;
  }
  return total;
}

Writing Tests

The built-in assert module provides simple assertion testing:

const assert = require('assert');

function add(a, b) { return a + b; }

assert.strictEqual(add(2, 3), 5);
assert.strictEqual(add(-1, 1), 0);
// assert.strictEqual(add(2, 2), 5); // Would throw AssertionError

Test Frameworks

Jest

Jest is the most popular testing framework. Install with: npm install --save-dev jest

// math.js
function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }
module.exports = { add, subtract };

// math.test.js
const { add, subtract } = require('./math');

describe('Math functions', () => {
  test('adds 1 + 2 to equal 3', () => {
    expect(add(1, 2)).toBe(3);
  });

  test('subtracts 5 - 3 to equal 2', () => {
    expect(subtract(5, 3)).toBe(2);
  });

  test('handles negative numbers', () => {
    expect(add(-1, -2)).toBe(-3);
    expect(subtract(-5, -3)).toBe(-2);
  });
});

Mocha & Chai

// Install: npm install --save-dev mocha chai

// math.test.js
const { expect } = require('chai');
const { add, subtract } = require('./math');

describe('Math functions', () => {
  it('should add two numbers', () => {
    expect(add(2, 3)).to.equal(5);
  });

  it('should subtract two numbers', () => {
    expect(subtract(10, 4)).to.equal(6);
  });
});

Test Runners

Configure your test script in package.json:

{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "test:mocha": "mocha 'tests/**/*.test.js'",
    "test:verbose": "jest --verbose"
  }
}

Mocking Dependencies

// Jest mocking
jest.mock('../services/database');
const db = require('../services/database');
db.getUser.mockResolvedValue({ id: 1, name: 'Alice' });

test('getUserName returns user name', async () => {
  const result = await getUserName(1);
  expect(result).toBe('Alice');
  expect(db.getUser).toHaveBeenCalledWith(1);
});

Integration Testing APIs

// Install: npm install --save-dev supertest

const request = require('supertest');
const app = require('../app');

describe('GET /api/users', () => {
  it('should return a list of users', async () => {
    const res = await request(app)
      .get('/api/users')
      .expect(200);

    expect(res.body).toBeInstanceOf(Array);
    expect(res.body[0]).toHaveProperty('name');
  });
});
Exercise: Write Jest tests for an Express.js task API. Test all CRUD endpoints (GET, POST, PUT, DELETE), including validation errors and 404 cases. Use supertest for HTTP integration testing.