The assert module provides assertion functions for testing. Here's how to use it effectively.
Basic Assertions#
1const assert = require('assert');
2
3// Basic equality
4assert.equal(1, 1); // Passes (loose equality)
5assert.equal(1, '1'); // Passes (loose equality)
6assert.strictEqual(1, 1); // Passes (strict equality)
7// assert.strictEqual(1, '1'); // Throws!
8
9// Not equal
10assert.notEqual(1, 2); // Passes
11assert.notStrictEqual(1, '1'); // Passes
12
13// Truthy/Falsy
14assert.ok(true); // Passes
15assert.ok(1); // Passes
16assert.ok('string'); // Passes
17// assert.ok(false); // Throws!
18// assert.ok(0); // Throws!
19
20// Direct assertions
21assert(true); // Same as assert.ok()
22assert(1 === 1);Strict Mode#
1const assert = require('assert').strict;
2// Or: const assert = require('assert/strict');
3
4// In strict mode, equal uses strict equality
5assert.equal(1, 1); // Passes
6// assert.equal(1, '1'); // Throws in strict mode!
7
8// Deep equality is also strict
9assert.deepEqual({ a: 1 }, { a: 1 }); // Passes
10// assert.deepEqual({ a: 1 }, { a: '1' }); // Throws!
11
12// Recommended: always use strict mode
13const { strict: assert } = require('assert');Deep Equality#
1const assert = require('assert').strict;
2
3// Deep object comparison
4assert.deepStrictEqual(
5 { a: 1, b: { c: 2 } },
6 { a: 1, b: { c: 2 } }
7); // Passes
8
9assert.deepStrictEqual(
10 [1, 2, [3, 4]],
11 [1, 2, [3, 4]]
12); // Passes
13
14// Not deep equal
15assert.notDeepStrictEqual(
16 { a: 1 },
17 { a: 2 }
18); // Passes
19
20// Works with various types
21assert.deepStrictEqual(
22 new Date('2021-01-01'),
23 new Date('2021-01-01')
24);
25
26assert.deepStrictEqual(
27 new Map([['a', 1]]),
28 new Map([['a', 1]])
29);
30
31assert.deepStrictEqual(
32 new Set([1, 2, 3]),
33 new Set([1, 2, 3])
34);
35
36// Prototype checking
37const obj1 = Object.create({ proto: true });
38const obj2 = Object.create(null);
39// assert.deepStrictEqual(obj1, obj2); // Throws - different prototypesError Assertions#
1const assert = require('assert').strict;
2
3// Assert throws
4assert.throws(
5 () => { throw new Error('Wrong'); },
6 Error
7);
8
9// With specific error
10assert.throws(
11 () => { throw new TypeError('Invalid'); },
12 TypeError
13);
14
15// With error message
16assert.throws(
17 () => { throw new Error('Specific error'); },
18 { message: 'Specific error' }
19);
20
21// With regex
22assert.throws(
23 () => { throw new Error('File not found'); },
24 /not found/
25);
26
27// With validation function
28assert.throws(
29 () => { throw new Error('Custom error'); },
30 (err) => {
31 return err instanceof Error && err.message.includes('Custom');
32 }
33);
34
35// Does not throw
36assert.doesNotThrow(
37 () => { return 42; }
38);
39
40// Async assertions
41async function failingAsync() {
42 throw new Error('Async error');
43}
44
45await assert.rejects(failingAsync, Error);
46
47await assert.rejects(
48 failingAsync,
49 { message: 'Async error' }
50);
51
52// Does not reject
53await assert.doesNotReject(
54 async () => { return 42; }
55);Custom Messages#
1const assert = require('assert').strict;
2
3// Add context to failures
4assert.equal(result, expected, 'Result should match expected value');
5
6assert.ok(user.isActive, `User ${user.id} should be active`);
7
8assert.strictEqual(
9 response.status,
10 200,
11 `Expected status 200, got ${response.status}`
12);
13
14// With Error object
15assert.fail(new Error('This test should not reach here'));
16
17// Fail with message
18assert.fail('Unreachable code executed');
19
20// AssertionError details
21try {
22 assert.strictEqual(1, 2, 'Numbers should match');
23} catch (err) {
24 console.log(err.message); // 'Numbers should match'
25 console.log(err.actual); // 1
26 console.log(err.expected); // 2
27 console.log(err.operator); // 'strictEqual'
28}Match and ifError#
1const assert = require('assert').strict;
2
3// Match - check if string matches regex
4assert.match('hello world', /world/);
5assert.match('test@example.com', /^\S+@\S+\.\S+$/);
6
7// Does not match
8assert.doesNotMatch('hello', /world/);
9
10// ifError - throws if value is truthy (for callbacks)
11assert.ifError(null); // Passes
12assert.ifError(undefined); // Passes
13// assert.ifError(new Error('fail')); // Throws the error
14
15// Common callback pattern
16function callback(err, result) {
17 assert.ifError(err); // Throws if error exists
18 assert.ok(result);
19}Testing Patterns#
1const assert = require('assert').strict;
2
3// Test function
4function add(a, b) {
5 return a + b;
6}
7
8// Basic test
9function testAdd() {
10 assert.strictEqual(add(1, 2), 3);
11 assert.strictEqual(add(-1, 1), 0);
12 assert.strictEqual(add(0, 0), 0);
13 console.log('✓ add tests passed');
14}
15
16// Test with setup/teardown
17function testDatabase() {
18 // Setup
19 const db = new Database();
20 db.connect();
21
22 try {
23 // Test
24 const user = db.createUser({ name: 'Alice' });
25 assert.ok(user.id);
26 assert.strictEqual(user.name, 'Alice');
27
28 const found = db.findUser(user.id);
29 assert.deepStrictEqual(found, user);
30
31 console.log('✓ database tests passed');
32 } finally {
33 // Teardown
34 db.disconnect();
35 }
36}
37
38// Async test
39async function testAsyncFunction() {
40 const result = await fetchData();
41 assert.ok(Array.isArray(result));
42 assert.ok(result.length > 0);
43 console.log('✓ async tests passed');
44}
45
46// Run tests
47async function runTests() {
48 testAdd();
49 testDatabase();
50 await testAsyncFunction();
51 console.log('All tests passed!');
52}
53
54runTests().catch(console.error);Custom Assertions#
1const assert = require('assert').strict;
2const { AssertionError } = assert;
3
4// Custom assertion function
5function assertInRange(value, min, max, message) {
6 if (value < min || value > max) {
7 throw new AssertionError({
8 message: message || `Expected ${value} to be between ${min} and ${max}`,
9 actual: value,
10 expected: `${min} - ${max}`,
11 operator: 'inRange',
12 });
13 }
14}
15
16// Usage
17assertInRange(5, 1, 10); // Passes
18// assertInRange(15, 1, 10); // Throws
19
20// Assert array contains
21function assertContains(array, item, message) {
22 if (!array.includes(item)) {
23 throw new AssertionError({
24 message: message || `Expected array to contain ${item}`,
25 actual: array,
26 expected: item,
27 operator: 'contains',
28 });
29 }
30}
31
32// Assert object has property
33function assertHasProperty(obj, prop, message) {
34 if (!(prop in obj)) {
35 throw new AssertionError({
36 message: message || `Expected object to have property "${prop}"`,
37 actual: Object.keys(obj),
38 expected: prop,
39 operator: 'hasProperty',
40 });
41 }
42}
43
44// Assert type
45function assertType(value, type, message) {
46 const actualType = typeof value;
47 if (actualType !== type) {
48 throw new AssertionError({
49 message: message || `Expected type ${type}`,
50 actual: actualType,
51 expected: type,
52 operator: 'typeOf',
53 });
54 }
55}Integration with Test Runners#
1// Works with Node.js test runner (v18+)
2const { describe, it } = require('node:test');
3const assert = require('assert').strict;
4
5describe('Calculator', () => {
6 it('should add numbers', () => {
7 assert.strictEqual(add(1, 2), 3);
8 });
9
10 it('should subtract numbers', () => {
11 assert.strictEqual(subtract(5, 3), 2);
12 });
13
14 it('should throw on division by zero', () => {
15 assert.throws(
16 () => divide(1, 0),
17 { message: 'Division by zero' }
18 );
19 });
20});
21
22// With Mocha
23describe('User Service', function() {
24 it('should create user', async function() {
25 const user = await createUser({ name: 'Test' });
26 assert.ok(user.id);
27 assert.strictEqual(user.name, 'Test');
28 });
29});Best Practices#
Usage:
✓ Use strict mode
✓ Provide descriptive messages
✓ Use deepStrictEqual for objects
✓ Test edge cases
Organization:
✓ Group related assertions
✓ Use setup/teardown patterns
✓ Test one thing per test
✓ Name tests descriptively
Error Handling:
✓ Test both success and failure
✓ Use assert.throws for errors
✓ Use assert.rejects for promises
✓ Include error messages
Avoid:
✗ Loose equality (==)
✗ Missing error messages
✗ Testing implementation details
✗ Ignoring async errors
Conclusion#
The Node.js assert module provides essential testing primitives. Use strict mode for reliable comparisons, provide clear error messages, and leverage deepStrictEqual for object comparisons. For larger projects, consider using it with a test runner like Node.js's built-in test runner or Mocha.