ماژول Assert در Node.js: راهنمای کامل

ماژول node:assert مجموعه‌ای از توابع Assertion برای بررسی صحت و درستی مقادیر و اینورینت‌ها در کد فراهم می‌کند. این ماژول در حالت‌های مختلف (strict و legacy) قابل استفاده است و در صورت نقض شرایط، خطای AssertionError تولید می‌کند. همچنین کلاس‌های AssertionError و Assert امکان سفارشی‌سازی و مدیریت پیشرفتهٔ Assertionها را فراهم می‌کنند.

Node.js AssertAssertionErrorStrict ModeLegacy ModedeepEqual vs deepStrictEqualAssert Class

~8 دقیقه مطالعه • بروزرسانی ۵ دی ۱۴۰۴

1. حالت Strict Assertion


در حالت strict، متدهای غیر-strict مانند assert.deepEqual() دقیقاً مانند نسخهٔ strict خود (assert.deepStrictEqual()) رفتار می‌کنند. پیام‌های خطا نیز شامل diff کامل بین مقادیر می‌شوند.

const assert = require('node:assert/strict');

assert.deepEqual([1], ['1']); 
// AssertionError با diff دقیق

برای غیرفعال کردن رنگ‌ها در خروجی، می‌توان از متغیرهای محیطی NO_COLOR یا NODE_DISABLE_COLORS استفاده کرد.

2. حالت Legacy Assertion


در حالت legacy، مقایسه‌ها با عملگر == انجام می‌شوند. این موضوع می‌تواند نتایج غیرمنتظره ایجاد کند.

const assert = require('node:assert');

// هشدار: این خطا تولید نمی‌کند!
assert.deepEqual(/a/gi, new Date());

3. کلاس AssertionError


تمام خطاهای تولیدشده توسط ماژول assert نمونه‌ای از AssertionError هستند. این کلاس از Error ارث‌بری می‌کند و ویژگی‌های زیر را دارد:

  • actual: مقدار واقعی
  • expected: مقدار مورد انتظار
  • operator: عملگر مقایسه
  • code: همیشه ERR_ASSERTION
  • generatedMessage: نشان می‌دهد پیام خطا خودکار تولید شده یا خیر

4. کلاس Assert


کلاس Assert امکان ساخت نمونه‌های مستقل با تنظیمات سفارشی را فراهم می‌کند.

گزینه‌ها:

  • diff: نمایش diff کامل یا ساده
  • strict: فعال‌سازی حالت strict
  • skipPrototype: نادیده گرفتن مقایسهٔ prototype در deep equality
const { Assert } = require('node:assert');
const assertInstance = new Assert({ diff: 'full' });
assertInstance.deepStrictEqual({ a: 1 }, { a: 2 });

نکته: اگر متدها را از نمونهٔ Assert جدا کنید (destructure)، تنظیمات سفارشی از دست می‌رود.

1. assert.doesNotMatch(string, regexp[, message])


بررسی می‌کند که رشتهٔ ورودی با الگوی RegExp تطابق نداشته باشد.

const assert = require('node:assert/strict');

assert.doesNotMatch('I will fail', /fail/); // خطا
assert.doesNotMatch('I will pass', /different/); // OK

اگر رشته با الگو تطابق داشته باشد یا نوع ورودی string نباشد، خطای AssertionError تولید می‌شود.

2. assert.doesNotReject(asyncFn[, error][, message])


بررسی می‌کند که Promise یا تابع async رد (reject) نشود.

await assert.doesNotReject(Promise.resolve('ok')); // OK
await assert.doesNotReject(Promise.reject(new Error('fail'))); // خطا

این متد مشابه assert.doesNotThrow() است اما برای Promiseها استفاده می‌شود.

3. assert.doesNotThrow(fn[, error][, message])


بررسی می‌کند که تابع مشخص‌شده خطا پرتاب نکند.

assert.doesNotThrow(() => { /* safe code */ }); // OK

assert.doesNotThrow(() => { throw new TypeError('Wrong'); }, TypeError);
// AssertionError: Got unwanted exception

اگر خطا پرتاب شود و نوع آن با پارامتر error تطابق داشته باشد، AssertionError تولید می‌شود.

4. assert.equal(actual, expected[, message])


در حالت legacy از عملگر == برای مقایسه استفاده می‌کند. در حالت strict معادل assert.strictEqual() است.

const assert = require('node:assert');

assert.equal(1, '1'); // OK در حالت legacy
assert.equal(NaN, NaN); // OK
assert.equal(1, 2); // خطا

5. assert.fail([message])


همیشه خطا تولید می‌کند. پیام خطا می‌تواند سفارشی باشد.

assert.fail(); // AssertionError: Failed
assert.fail('boom'); // AssertionError: boom
assert.fail(new TypeError('need array')); // TypeError

6. assert.ifError(value)


اگر مقدار ورودی null یا undefined نباشد، آن را به‌عنوان خطا پرتاب می‌کند. برای بررسی آرگومان خطا در callbackها مفید است.

assert.ifError(null); // OK
assert.ifError('error'); // AssertionError: got unwanted exception

7. assert.match(string, regexp[, message])


بررسی می‌کند که رشتهٔ ورودی با الگوی RegExp تطابق داشته باشد.

assert.match('I will pass', /pass/); // OK
assert.match('I will fail', /pass/); // خطا

8. assert.notDeepEqual(actual, expected[, message])


بررسی می‌کند که دو مقدار به‌صورت عمیق برابر نباشند. معکوس assert.deepEqual().

const obj1 = { a: { b: 1 } };
const obj2 = { a: { b: 2 } };

assert.notDeepEqual(obj1, obj2); // OK
assert.notDeepEqual(obj1, obj1); // خطا

نتیجه‌گیری


ماژول assert در Node.js ابزار قدرتمندی برای تست و اعتبارسنجی کد است. متدهای پیشرفته مانند doesNotMatch، doesNotReject، doesNotThrow و ifError امکان مدیریت دقیق‌تر سناریوهای پیچیده را فراهم می‌کنند. استفادهٔ درست از این متدها باعث می‌شود تست‌ها شفاف‌تر و خطاها قابل‌ردیابی‌تر باشند.

1. assert.notDeepStrictEqual(actual, expected[, message])


بررسی می‌کند که دو مقدار به‌صورت عمیق و strict برابر نباشند. معکوس assert.deepStrictEqual().

const assert = require('node:assert/strict');

assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); // OK

اگر مقادیر به‌صورت عمیق و strict برابر باشند، خطای AssertionError تولید می‌شود.

2. assert.notEqual(actual, expected[, message])


در حالت legacy از عملگر != برای مقایسه استفاده می‌کند. در حالت strict معادل assert.notStrictEqual() است.

const assert = require('node:assert');

assert.notEqual(1, 2); // OK
assert.notEqual(1, 1); // خطا
assert.notEqual(1, '1'); // خطا در حالت legacy

3. assert.notStrictEqual(actual, expected[, message])


بررسی می‌کند که دو مقدار به‌صورت strict برابر نباشند. مقایسه بر اساس Object.is() انجام می‌شود.

const assert = require('node:assert/strict');

assert.notStrictEqual(1, 2); // OK
assert.notStrictEqual(1, 1); // خطا
assert.notStrictEqual(1, '1'); // OK

4. assert.ok(value[, message])


بررسی می‌کند که مقدار truthy باشد. معادل assert.equal(!!value, true).

const assert = require('node:assert/strict');

assert.ok(true); // OK
assert.ok(1); // OK
assert.ok(false, 'it\'s false'); // خطا با پیام سفارشی
assert.ok(); // خطا: No value argument passed

در REPL پیام خطا متفاوت از فایل اجرا خواهد بود.

5. assert.rejects(asyncFn[, error][, message])


بررسی می‌کند که Promise یا تابع async رد (reject) شود. مشابه assert.throws() اما برای کدهای async.

const assert = require('node:assert/strict');

(async () => {
  await assert.rejects(
    async () => { throw new TypeError('Wrong value'); },
    { name: 'TypeError', message: 'Wrong value' }
  );
})();

پارامتر error می‌تواند کلاس خطا، RegExp، تابع اعتبارسنجی یا شیء باشد. اگر رشته به‌عنوان آرگومان دوم داده شود، به‌عنوان پیام در نظر گرفته می‌شود نه نوع خطا.

نتیجه‌گیری


ماژول assert در Node.js ابزار قدرتمندی برای تست و اعتبارسنجی کد است. متدهای notDeepStrictEqual، notEqual، notStrictEqual، ok و rejects امکان بررسی دقیق‌تر سناریوهای مختلف را فراهم می‌کنند و استفادهٔ درست از آن‌ها باعث می‌شود تست‌ها شفاف‌تر و خطاها قابل‌ردیابی‌تر باشند.

5. متدهای اصلی


assert(value[, message])

بررسی می‌کند که مقدار truthy باشد. معادل assert.ok().

assert.deepEqual()

در حالت legacy از == استفاده می‌کند و ممکن است نتایج غیرمنتظره داشته باشد. در حالت strict معادل assert.deepStrictEqual() است.

assert.deepStrictEqual()

بررسی دقیق بر اساس Object.is() و مقایسهٔ prototype و type tag.

const assert = require('node:assert/strict');

// خطا چون 1 !== '1'
assert.deepStrictEqual({ a: 1 }, { a: '1' });

6. جزئیات مقایسه در deepEqual و deepStrictEqual


  • مقادیر primitive: در legacy با ==، در strict با Object.is()
  • Prototype: در legacy نادیده گرفته می‌شود، در strict مقایسه می‌شود
  • Symbolها: در strict مقایسه می‌شوند
  • Map و Set: کلیدها و آیتم‌ها بدون ترتیب مقایسه می‌شوند
  • WeakMap و WeakSet: فقط در صورت یکسان بودن مرجع برابر هستند
  • RegExp: source و flags همیشه مقایسه می‌شوند

نتیجه‌گیری


ماژول assert ابزاری قدرتمند برای تست و اعتبارسنجی در Node.js است. با انتخاب حالت مناسب (strict یا legacy) و استفاده از کلاس‌های AssertionError و Assert می‌توان کنترل دقیق‌تری بر تست‌ها و پیام‌های خطا داشت. توصیه می‌شود همیشه از حالت strict استفاده شود تا نتایج قابل پیش‌بینی و دقیق حاصل شود.

1. assert.strictEqual(actual, expected[, message])


بررسی می‌کند که دو مقدار به‌صورت strict برابر باشند. مقایسه بر اساس Object.is() انجام می‌شود.

const assert = require('node:assert/strict');

assert.strictEqual(1, 2);
// خطا: 1 !== 2

assert.strictEqual(1, 1);
// OK

assert.strictEqual('Hello foobar', 'Hello World!');
// خطا با diff دقیق

const apples = 1;
const oranges = 2;
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
// خطا با پیام سفارشی

assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
// پرتاب TypeError سفارشی

اگر مقادیر برابر نباشند، خطای AssertionError تولید می‌شود. اگر پیام خطا یک نمونهٔ Error باشد، همان خطا پرتاب می‌شود.

2. assert.throws(fn[, error][, message])


بررسی می‌کند که تابع مشخص‌شده خطا پرتاب کند.

گزینه‌های اعتبارسنجی خطا:

  • کلاس خطا (مثلاً Error)
  • RegExp برای بررسی پیام خطا
  • تابع اعتبارسنجی که باید true برگرداند
  • شیء اعتبارسنجی که ویژگی‌های خطا را بررسی می‌کند
const assert = require('node:assert/strict');

assert.throws(() => { throw new Error('Wrong value'); }, Error); // OK

assert.throws(() => { throw new Error('Wrong value'); }, /^Error: Wrong value$/); // OK

assert.throws(
  () => { throw new Error('Wrong value'); },
  (err) => {
    assert(err instanceof Error);
    assert(/value/.test(err));
    return true;
  },
  'unexpected error',
);

نکته: استفاده از رشته به‌عنوان آرگومان دوم توصیه نمی‌شود چون می‌تواند باعث خطاهای مبهم شود.

3. assert.partialDeepStrictEqual(actual, expected[, message])


بررسی می‌کند که مقادیر به‌صورت عمیق برابر باشند، اما فقط ویژگی‌هایی که در شیء expected وجود دارند بررسی می‌شوند. این متد نسخهٔ گسترده‌تر assert.deepStrictEqual() است.

const assert = require('node:assert');

assert.partialDeepStrictEqual({ a: { b: { c: 1 } } }, { a: { b: { c: 1 } } }); // OK
assert.partialDeepStrictEqual({ a: 1, b: 2, c: 3 }, { b: 2 }); // OK
assert.partialDeepStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9], [4, 5, 8]); // OK
assert.partialDeepStrictEqual(new Set([{ a: 1 }, { b: 1 }]), new Set([{ a: 1 }])); // OK
assert.partialDeepStrictEqual(new Map([['key1','value1'], ['key2','value2']]), new Map([['key2','value2']])); // OK
assert.partialDeepStrictEqual(123n, 123n); // OK

assert.partialDeepStrictEqual({ a: 1 }, { a: 1, b: 2 }); // خطا
assert.partialDeepStrictEqual({ a: { b: 2 } }, { a: { b: '2' } }); // خطا

این متد برای تست بخشی از ساختار داده‌ها مفید است، بدون نیاز به بررسی تمام ویژگی‌ها.

نتیجه‌گیری


ماژول assert در Node.js ابزار قدرتمندی برای تست و اعتبارسنجی کد است. متدهای strictEqual، throws و partialDeepStrictEqual امکان بررسی دقیق‌تر سناریوهای مختلف را فراهم می‌کنند و استفادهٔ درست از آن‌ها باعث می‌شود تست‌ها شفاف‌تر و خطاها قابل‌ردیابی‌تر باشند.

نوشته و پژوهش شده توسط دکتر شاهین صیامی