Testing & Integration in Web Applications
Seoul National University of Science and Technology
Information Technology Management
Lecture slides index
June 4, 2025

const test = require('node:test');
const assert = require('node:assert');
const sum = (a, b) => a + b;
test.describe('Operators Test Suite', () => {
test.it('Should sum two numbers', () => {
assert.strictEqual(sum(1, 2), 3);
});
});describe to group related tests (e.g., for a module or function).it to define individual test cases.assert to check that the output matches the expected result.utils.js) that perform several arithmetic operations: sum, multiply and divide.utils.js
sum function is summing two numbers, the multiply function is multiplying two numbers and the divide function is divinding two numbers correctly.utils.jstest and assert.node_test in the root directory of your project.utils.test.js
[FILE_TO_TEST].test.jssum, multiply and divide.divide test suite)node_test/utils.test.js
const test = require('node:test');
const assert = require('node:assert');
const { sum, multiply, divide } = require('../utils');
test.describe("Utils Test Suite: sum", () => {
test.it("Should sum two numbers", () => {
assert.strictEqual(sum(1, 2), 3);
});
});
test.describe("Utils Test Suite: multiply", () => {
test.it("Should multiply two numbers", () => {
assert.strictEqual(multiply(5, 3), 15);
});
});
test.describe("Utils Test Suite: divide", () => {
test.it("Should divide two positive numbers", () => {
assert.strictEqual(divide(10, 2), 5);
});
test.it("Should divide a positive and a negative number", () => {
assert.strictEqual(divide(-10, 2), -5);
});
test.it("Should return Infinity when dividing by 0", () => {
assert.strictEqual(divide(10, 0), Infinity);
});
test.it("Should return NaN when dividing 0 by 0", () => {
assert.ok(Number.isNaN(divide(0, 0)));
});
});package.json in the scripts property.{
"name": "unit_testing",
"version": "1.0.0",
"main": "app.js",
"scripts": {
"node-test": "node --test \"node_test/*.test.js\""
},
"author": "jobregon",
"license": "MIT",
"description": ""
}**/*.test.{cjs,mjs,js}**/*-test.{cjs,mjs,js}**/*_test.{cjs,mjs,js}npm run node-test
jest.confg.js to specify that we should ignore the node_test folder (this is not necessary if you are only using Jest as a test library)package.json file:utils.js using Jestexpect() is used to wrap the actual value you want to test..toBe() checks that the actual value is exactly equal (using ===) to the expected value.toBeNull(), toThrow(), (more in this link)describe and it functions, so we don’t need to import them.jest_test/utils.test.js
const { sum, multiply, divide } = require('../utils.js');
describe("Utils Test Suite: sum", () => {
test("Should sum two numbers", () => {
expect(sum(1, 2)).toBe(3);
});
});
describe("Utils Test Suite: multiply", () => {
test("Should multiply two numbers", () => {
expect(multiply(5, 3)).toBe(15);
});
});
describe("Utils Test Suite: divide", () => {
test("Should divide two positive numbers", () => {
expect(divide(10, 2)).toBe(5);
});
test("Should divide a positive and a negative number", () => {
expect(divide(-10, 2)).toBe(-5);
});
test("Should return Infinity when dividing by 0", () => {
expect(divide(10, 0)).toBe(Infinity);
});
test("Should return NaN when dividing 0 by 0", () => {
expect(Number.isNaN(divide(0, 0))).toBe(true);
});
});npm run jest-testpackage.json:{
"scripts": {
"node-test": "node --test \"node_test/*.test.js\"",
"jest-test": "jest",
"jest-test:coverage": "jest --coverage",
"node-test:coverage": "node --test --experimental-test-coverage \"node_test/*.test.js\""
}
}--experimental-test-coverage flag to enable this featuresubstract, to our utils.js file:npm run node-test:coverage and npm run jest-test:coveragesubtract function.Node.js

Jest

index.html file located in coverage/lcov-report in our browser to see the results.utils.js

GET /api/flights/:id
app.get(
'/api/flights/:id',
async (req, res) => {
try {
const flightId = parseInt(req.params.id);
// 1) Flight info
const flight = await getFlight(flightId);
// check if flight exists
if (!flight) {
res.sendStatus(404);
} else {
// 2) Assigned passengers (persons)
const passengers = await getPassengers(flightId);
res.json({
id: flight.id,
origin: flight.origin,
destination: flight.destination,
duration: flight.duration,
passengers: passengers
});
}
} catch (err) {
res.status(500).json({ message: err.message });
}
}
);const request = require('supertest');
const app = require('../app'); // your Express app
test('GET /api/flights returns 200', async () => {
const res = await request(app).get('/api/flights');
expect(res.statusCode).toBe(200);
});Important
Do not forget to install Jest in the airline project and add the test scripts to package.json as we learned before.
.listen()app.js to export the app:const express = require('express');
const app = express();
// routes go here...
module.exports = app;server.js
app and separate app.listen() into its own file (e.g.,server.js) because:
jest.mock() allows os to mock modules by erasing the actual implementation of functions and capturing calls to the functions in the modulemockResolvedValue for .getFlight that returns the data we want to use in our tests.it.todo function marks the tests that we need to add.
tests/flight.test.js
const request = require('supertest');
const app = require('../app');
// Mock your database functions
jest.mock('../db');
const { getFlight, getPassengers } = require('../db');
describe('GET /api/flights/:id', () => {
it('should return 404 if flight not found', async () => {
getFlight.mockResolvedValue(null); // simulate no flight found
const res = await request(app).get('/api/flights/999');
expect(res.statusCode).toBe(404);
});
it('should return flight with passengers', async () => {
getFlight.mockResolvedValue({
id: 1,
origin: 'Seoul',
destination: 'Tokyo',
duration: 120
});
getPassengers.mockResolvedValue([
{ id: 1, first: 'Alice', last: 'Kim' },
{ id: 2, first: 'Bob', last: 'Lee' }
]);
const res = await request(app).get('/api/flights/1');
expect(res.statusCode).toBe(200);
expect(res.body).toEqual({
id: 1,
origin: 'Seoul',
destination: 'Tokyo',
duration: 120,
passengers: [
{ id: 1, first: 'Alice', last: 'Kim' },
{ id: 2, first: 'Bob', last: 'Lee' }
]
});
});
it('should return 500 on error', async () => {
getFlight.mockImplementation(() => {
throw new Error('DB failed');
});
const res = await request(app).get('/api/flights/1');
expect(res.statusCode).toBe(500);
expect(res.body).toHaveProperty('message', 'DB failed');
});
});
describe("GET /api/flights", () => {
it.todo("Should return an empty array when there's no flights data")
it.todo("Should return all the flights")
})npm run jest-test:coverage/api/flights/)app.js has 50% of coverage (app.use functions were not tested)db.js has 0% of coverage



GitHub Actions
npm ci is similar to npm install, except it’s meant to be used in automated environments.github/workflows/node.js.yml
name: Node.js CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm jest-testDocker


Web Programming