assert.equal()

Compares two values with == and throws an AssertionError when they are not loosely equal.

Signature
assert.equal(actual, expected[, message])
  • Added in Node.js v0.1.21

Parameters

ParameterTypeDescription
$actualanyThe value produced by the code under test.
$expectedanyThe value it is compared against, using ==.
$messageoptionalstring | Error | FunctionError message, an Error instance to throw instead, or a function called on failure.

Errors

Throws an AssertionError with code ERR_ASSERTION when actual == expected is false; if message is an Error instance, that error is thrown instead.

Changelog

  • PHP v26.0.0Message may now be a printf-like format string or function.
  • PHP v16.0.0, v14.18.0In legacy assertion mode, the status changed from Deprecated to Legacy.
  • PHP v14.0.0NaN is now treated as identical if both sides are NaN.

assert.equal() compares its two arguments with the loose equality operator, ==. Node documents it as Legacy: Use assert.strictEqual() instead. It is not deprecated and will not warn, but there is no case where it is the better tool.

What == lets through

Because coercion runs before the comparison, all of these pass: 1 and '1', null and undefined, 0 and false, 0 and '', 1 and true. That is the failure mode: a function that starts returning the string '200' where it used to return the number 200 keeps every equal() test green.

NaN and objects

Since Node 14 a special case makes assert.equal(NaN, NaN) pass, even though plain NaN == NaN is false. Objects are still compared by reference — assert.equal({}, {}) fails, because == never looks inside. For structural comparison use assert.deepStrictEqual().

Getting off it

Requiring node:assert/strict instead of node:assert makes equal behave as strictEqual across the whole file, which is the cheapest way to migrate an old suite.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Read and understand assertions in an older test suite written before strict mode existed
  • Compare a value against null while deliberately treating undefined as a match
  • Migrate a legacy suite by switching the import to node:assert/strict and fixing what breaks

Frequently asked questions

Is assert.equal() deprecated in Node.js?

No — it is classified as Legacy, not Deprecated, since v16.0.0 and v14.18.0, so it emits no warning and is not scheduled for removal. The docs still direct you to assert.strictEqual() instead, because == comparison hides type regressions.

Why does assert.equal(NaN, NaN) pass when NaN == NaN is false?

Node added an explicit special case in v14.0.0 so that two NaN values are treated as identical. Before that version the assertion failed, which surprised people testing numeric parsers.

Does assert.equal() compare objects?

No, it compares object references with ==, so assert.equal({a: 1}, {a: 1}) throws even though the objects look the same. Use assert.deepStrictEqual() to compare structure.

More examples

The regression assert.equal() will not catch

Both parser versions satisfy assert.equal even though one returns a string and the other a number. Only strictEqual reports the type change, which is why a suite built on equal() can stay green through a breaking refactor.

Example · javascript
const assert = require('node:assert');

// Version 1 of the parser returned a number.
function parseStatusV1(line) {
  return Number(line.split(' ')[1]);
}

// Version 2 accidentally returns the raw string.
function parseStatusV2(line) {
  return line.split(' ')[1];
}

const line = 'HTTP/1.1 200 OK';

assert.equal(parseStatusV1(line), 200); // passes
assert.equal(parseStatusV2(line), 200); // ALSO passes — '200' == 200
console.log('both versions passed assert.equal');

try {
  assert.strictEqual(parseStatusV2(line), 200);
} catch (err) {
  console.log('strictEqual catches it:', err.code);
}

Switch the whole file to strict mode

Under node:assert/strict the legacy names are rebound to their strict counterparts, so both calls that previously passed now throw. This is the standard one-line migration: change the import, then fix every assertion that starts failing.

Example · javascript
// Legacy file:
const assert = require('node:assert');
assert.equal(1, '1');       // passes
assert.deepEqual({ a: 1 }, { a: '1' }); // passes

// Same file, one import changed:
const strict = require('node:assert/strict');
try {
  strict.equal(1, '1');     // equal is now strictEqual
} catch (err) {
  console.log('strict.equal ->', err.code); // ERR_ASSERTION
}
try {
  strict.deepEqual({ a: 1 }, { a: '1' });   // now deepStrictEqual
} catch (err) {
  console.log('strict.deepEqual ->', err.code); // ERR_ASSERTION
}

Custom messages and the AssertionError fields

The thrown AssertionError exposes actual, expected and operator as properties, so a test reporter can render its own diff. The operator field is the literal string '==', which is how you can tell a legacy assertion from a strict one when reading a failure report.

Example · javascript
const assert = require('node:assert');

const expectedRows = 3;
const rows = ['a', 'b'];

try {
  assert.equal(rows.length, expectedRows, `expected ${expectedRows} rows, got ${rows.length}`);
} catch (err) {
  console.log(err.name);      // AssertionError
  console.log(err.code);      // ERR_ASSERTION
  console.log(err.actual);    // 2
  console.log(err.expected);  // 3
  console.log(err.operator);  // ==
  console.log(err.message);   // expected 3 rows, got 2
}

Discussion

  • Be the first to comment on this lesson.