วิธีใช้ Assert ใน Node.js: คู่มือฉบับปฏิบัติจริง

INEZA Felin-Michel

INEZA Felin-Michel

22 May 2026

วิธีใช้ Assert ใน Node.js: คู่มือฉบับปฏิบัติจริง

Apidog สำหรับองค์กร

ติดตั้งภายในองค์กร

SSO & RBAC

รองรับ SOC 2

สำรวจ Apidog Enterprise

ไม่ว่าคุณจะใช้เฟรมเวิร์กทดสอบใดๆ ไม่ว่าจะเป็น Jest, Mocha หรือ node:test ล้วนแล้วแต่มีแนวคิดง่ายๆ คือ: ระบุสิ่งที่คุณคาดหวัง จากนั้นส่งข้อผิดพลาดหากความจริงไม่เป็นไปตามนั้น Node.js มีแนวคิดนั้นมาให้ในรูปแบบโมดูลในตัวที่เรียกว่า assert ไม่ต้องติดตั้ง ไม่ต้องพึ่งพาอาศัย เพียงแค่ require และเริ่มตรวจสอบข้อสันนิษฐานของคุณได้เลย

โมดูล assert นั้นคุ้มค่าที่จะเรียนรู้ด้วยตัวมันเอง มันช่วยในการตรวจสอบความถูกต้องอย่างรวดเร็วในสคริปต์ เป็นรากฐานของตัวรันการทดสอบหลายตัว และสอนให้คุณเข้าใจว่าการยืนยัน (assertion) คืออะไรก่อนที่เฟรมเวิร์กใดๆ จะมาตกแต่งเพิ่มเติม คู่มือนี้ครอบคลุมถึงเมธอดที่สำคัญ ความแตกต่างระหว่างโหมด strict และ legacy ที่ทำให้คนสับสน วิธีการยืนยันข้อผิดพลาดและโค้ดแบบ async และวิธีที่โมดูลเดียวกันนี้ช่วยให้คุณตรวจสอบการตอบกลับของ API ได้

โมดูล assert ทำอะไร

การยืนยัน (assertion) คือข้อความที่ต้องเป็นจริงเพื่อให้โปรแกรมของคุณถือว่าถูกต้อง เมื่อคุณเขียน assert.strictEqual(total, 100) คุณกำลังประกาศว่า total ควรจะเท่ากับ 100 หากเป็นเช่นนั้น จะไม่มีอะไรเกิดขึ้นและโปรแกรมจะทำงานต่อไป หากไม่เป็นเช่นนั้น assert จะส่ง AssertionError ซึ่งจะหยุดการทำงานและบอกคุณว่าเกิดอะไรขึ้น

นำเข้าโมดูล รูปแบบที่ทันสมัยและแนะนำคือเวอร์ชัน strict:

const assert = require('node:assert/strict');
// หรือกับ ES modules:
// import assert from 'node:assert/strict';

การยืนยันที่ง่ายที่สุดคือการตรวจสอบว่าค่าเป็น truthy:

const user = getUser(42);
assert(user, 'getUser should return a user object');

อาร์กิวเมนต์แรกคือค่าที่กำลังทดสอบ อาร์กิวเมนต์ที่สอง ซึ่งเป็นทางเลือก คือข้อความที่จะแสดงเมื่อการยืนยันล้มเหลว ควรเขียนข้อความนี้เสมอ ความล้มเหลวที่ระบุว่า “getUser should return a user object” มีประโยชน์มากกว่า AssertionError เปล่าๆ การทำความเข้าใจการยืนยันยังช่วยได้เมื่อคุณเปลี่ยนไปใช้ การยืนยัน API เฉพาะในเครื่องมือทดสอบ

โหมด Strict เทียบกับโหมด Legacy

นี่คือสิ่งสำคัญที่สุดที่ต้องทำความเข้าใจให้ถูกต้อง โมดูล assert มีสองโหมด

โหมด Legacy ซึ่งคุณได้จาก require('node:assert') ใช้การเปรียบเทียบแบบหลวมๆ (==) สำหรับ assert.equal และ assert.deepEqual นั่นหมายความว่า assert.equal(1, '1') ผ่าน เพราะ 1 == '1' เป็นจริงใน JavaScript การเปรียบเทียบแบบหลวมๆ เป็นแหล่งที่มาของข้อผิดพลาดที่รู้จักกันดี

โหมด Strict ซึ่งคุณได้จาก require('node:assert/strict') ใช้การเปรียบเทียบแบบเข้มงวด (===) สำหรับทุกอย่าง assert.equal(1, '1') ล้มเหลว อย่างที่ควรจะเป็น เพราะชนิดข้อมูลแตกต่างกัน

const looseAssert = require('node:assert');
looseAssert.equal(1, '1');        // ผ่าน, น่าประหลาดใจและอันตราย

const strict = require('node:assert/strict');
strict.equal(1, '1');             // ส่ง AssertionError, ถูกต้อง

ใช้โหมด strict ไม่มีเหตุผลที่ดีที่จะยอมรับการเปรียบเทียบแบบหลวมๆ ในการทดสอบ ส่วนที่เหลือของคู่มือนี้จะถือว่าใช้ node:assert/strict โดยที่ assert.equal ทำงานเหมือนกับ assert.strictEqual

การเปรียบเทียบค่า: equal และ strictEqual

assert.strictEqual(actual, expected) ตรวจสอบว่าค่าสองค่าเหมือนกันด้วย === เป็นฟังก์ชันหลักสำหรับค่าดั้งเดิม (primitives) เช่น ตัวเลข, สตริง และบูลีน

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

function priceWithTax(price, rate) {
  return price + price * rate;
}

assert.strictEqual(priceWithTax(100, 0.08), 108, 'tax calc should add 8 percent');
assert.strictEqual(typeof priceWithTax(100, 0.08), 'number', 'result should be a number');

นอกจากนี้ยังมี assert.notStrictEqual ซึ่งจะผ่านเมื่อค่าสองค่าไม่เหมือนกัน ใช้เพื่อยืนยันว่าค่ามีการเปลี่ยนแปลง:

const before = getCacheKey();
refreshCache();
const after = getCacheKey();
assert.notStrictEqual(before, after, 'cache key should change after refresh');

สำหรับอ็อบเจกต์และอาร์เรย์ strictEqual จะไม่ช่วย สองอ็อบเจกต์ literal ที่มีเนื้อหาเหมือนกันจะมีการอ้างอิงที่ต่างกัน ดังนั้น === จะคืนค่า false นี่คือสิ่งที่เป็นวัตถุประสงค์ของการเปรียบเทียบแบบ deep equality

การเปรียบเทียบอ็อบเจกต์: deepStrictEqual

assert.deepStrictEqual(actual, expected) เปรียบเทียบโครงสร้างและค่าแบบเรียกซ้ำ อ็อบเจกต์สองตัวจะผ่านหากทุกคีย์มีค่าที่เท่ากันอย่างเข้มงวด ตลอดทั้งโครงสร้าง

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

function buildOrder(id, items) {
  return { id, items, status: 'pending' };
}

assert.deepStrictEqual(
  buildOrder(7, ['keyboard', 'mouse']),
  { id: 7, items: ['keyboard', 'mouse'], status: 'pending' },
  'order object should match expected shape'
);

นี่คือเมธอดที่คุณจะใช้บ่อยที่สุดเมื่อทดสอบฟังก์ชันที่ส่งคืนอ็อบเจกต์ โดยเฉพาะอย่างยิ่งเมื่อทดสอบการตอบกลับของ API เนื่องจากเนื้อหา JSON เป็นอ็อบเจกต์ ส่วนคู่ของมัน assert.notDeepStrictEqual จะผ่านเมื่อโครงสร้างแตกต่างกัน

ข้อควรระวังอย่างหนึ่ง: deepStrictEqual ตรวจสอบชนิดข้อมูลด้วย คุณสมบัติที่เก็บตัวเลข 7 จะไม่ตรงกับคุณสมบัติที่เก็บสตริง '7' ความเข้มงวดนี้เป็นคุณสมบัติที่สำคัญ มันช่วยตรวจจับการเปลี่ยนแปลงชนิดข้อมูลในข้อมูลของคุณ หากคุณกำลังทดสอบฟังก์ชันที่มีชุดอินพุตหลายชุด คู่มือของเราเกี่ยวกับการ ทดสอบ API แบบขับเคลื่อนด้วยข้อมูลด้วย CSV และ JSON แสดงให้เห็นวิธีการปรับขนาดการยืนยันข้ามชุดข้อมูล

เมื่อ deepStrictEqual ล้มเหลว Node จะพิมพ์ส่วนที่แตกต่าง (diff) ที่เน้นย้ำว่าคุณสมบัติใดไม่ตรงกันอย่างชัดเจน ส่วนที่แตกต่างนั้นเป็นหนึ่งในสิ่งที่ประโยชน์ที่สุดของโมดูลนี้ แทนที่จะต้องจ้องดูอ็อบเจกต์ขนาดใหญ่สองตัวเพื่อพยายามหาความแตกต่าง คุณสามารถอ่านเพียงไม่กี่บรรทัดที่เน้นไว้ สำหรับข้อมูลที่ซ้อนกัน นั่นก็เพียงพอแล้วที่จะเลือกใช้ deepStrictEqual แทนการตรวจสอบแต่ละฟิลด์ด้วย strictEqual ด้วยตนเอง

การจับคู่บางส่วนด้วย assert.match และ assert.ok

ไม่ใช่ทุกการตรวจสอบที่ต้องการความเท่าเทียมกันแบบเต็มรูปแบบ บางครั้งคุณเพียงแค่สนใจว่าค่าดูถูกต้องคร่าวๆ assert.ok(value) จะผ่านเมื่อใดก็ตามที่ค่าเป็น truthy ซึ่งเป็นเครื่องมือที่เหมาะสมสำหรับการตรวจสอบ "สิ่งนี้ควรมีอยู่": สตริงที่ไม่ว่างเปล่า, อ็อบเจกต์ที่ถูกกำหนด, จำนวนที่ไม่ใช่ศูนย์

assert.match(string, regexp) ตรวจสอบว่าสตริงตรงกับนิพจน์ทั่วไป (regular expression) และ assert.doesNotMatch ตรวจสอบสิ่งที่ตรงข้าม สิ่งเหล่านี้มีประโยชน์สำหรับค่าที่เนื้อหาที่แน่นอนแตกต่างกัน แต่รูปร่างคงที่

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

function generateOrderId() {
  return 'ORD-' + Date.now();
}

const id = generateOrderId();

// timestamp ที่แน่นอนเปลี่ยนไป ดังนั้นให้ยืนยันรูปแบบ ไม่ใช่ค่า
assert.match(id, /^ORD-\d+$/, 'order id should be ORD- followed by digits');
assert.ok(id.length > 4, 'order id should not be empty');

รูปแบบนี้มีความสำคัญอย่างยิ่งสำหรับการทดสอบ API โดยเฉพาะอย่างยิ่งที่การตอบกลับมี timestamp, ID ที่สร้างขึ้น และโทเค็นที่คุณไม่สามารถคาดเดาได้ คุณยืนยันรูปแบบด้วย match และการมีอยู่ด้วย ok และคุณสงวน strictEqual ไว้สำหรับค่าที่คุณควบคุมได้จริง

การยืนยันว่าโค้ดมีการโยนข้อผิดพลาด

บางครั้งพฤติกรรมที่ถูกต้องหมายถึงการโยนข้อผิดพลาด assert.throws(fn, expectedError) จะรันฟังก์ชันและผ่านก็ต่อเมื่อฟังก์ชันนั้นโยนข้อผิดพลาด

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

function parsePort(value) {
  const port = Number(value);
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
    throw new RangeError('port must be an integer between 1 and 65535');
  }
  return port;
}

// ผ่าน: อินพุตที่ไม่ถูกต้องควรโยน RangeError
assert.throws(
  () => parsePort('70000'),
  RangeError,
  'out-of-range port should throw RangeError'
);

// คุณยังสามารถจับคู่ข้อความแสดงข้อผิดพลาดด้วย regex
assert.throws(
  () => parsePort('abc'),
  /must be an integer/,
  'non-numeric port should throw a descriptive error'
);

// ผ่าน: อินพุตที่ถูกต้องไม่ควรโยนข้อผิดพลาด
assert.doesNotThrow(
  () => parsePort('8080'),
  'a valid port should not throw'
);

โปรดทราบว่าคุณส่งฟังก์ชัน ไม่ใช่การเรียก assert.throws(parsePort('70000')) จะรัน parsePort ก่อนที่ assert จะเห็นมัน และข้อผิดพลาดจะหลุดรอดไปโดยไม่ถูกจับกุม ควรครอบมันไว้เสมอ: () => parsePort('70000')

การยืนยันโค้ดแบบ Asynchronous: rejects

โค้ด Node.js สมัยใหม่เต็มไปด้วย Promise และ Promise ที่ถูกปฏิเสธ (rejected) ก็เหมือนกับการโยนข้อผิดพลาดแบบ Asynchronous assert.rejects และ assert.doesNotReject จัดการกรณีนี้ ทั้งคู่จะคืนค่า Promise ดังนั้นคุณต้องใช้ await กับมัน

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

async function fetchUser(id) {
  if (typeof id !== 'number') {
    throw new TypeError('id must be a number');
  }
  // ... การค้นหาจริงจะอยู่ที่นี่
  return { id, name: 'Dana Lee' };
}

async function runTests() {
  // ผ่าน: อินพุตที่ไม่ถูกต้องจะถูกปฏิเสธด้วย TypeError
  await assert.rejects(
    fetchUser('not-a-number'),
    TypeError,
    'string id should reject'
  );

  // ผ่าน: อินพุตที่ถูกต้องจะถูกแก้ไขโดยไม่ถูกปฏิเสธ
  await assert.doesNotReject(
    fetchUser(101),
    'valid id should resolve cleanly'
  );
}

runTests();

การลืม await ในการเรียก assert.rejects เป็นข้อผิดพลาดที่พบบ่อย หากไม่มี await ฟังก์ชันทดสอบจะทำงานเสร็จก่อนที่การยืนยันจะเสร็จสมบูรณ์ และความล้มเหลวจะกลายเป็นการปฏิเสธที่ไม่ได้ถูกจัดการ (unhandled rejection) แทนที่จะเป็นข้อผิดพลาดในการทดสอบที่ชัดเจน

การใช้ assert เพื่อทดสอบการตอบกลับของ API

โมดูล assert มีประโยชน์อย่างแท้จริงสำหรับการตรวจสอบผลลัพธ์ของการร้องขอ HTTP หลังจากที่คุณเรียกปลายทาง (endpoint) คุณจะมีสถานะโค้ดและเนื้อหา JSON ซึ่งทั้งสองอย่างนี้เป็นสิ่งที่ต้องยืนยัน

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

async function testGetUser() {
  const res = await fetch('https://api.example.com/users/101');

  // ตรวจสอบสถานะโค้ด
  assert.strictEqual(res.status, 200, 'GET /users/101 should return 200');

  const body = await res.json();

  // ตรวจสอบรูปร่างและชนิดข้อมูลของการตอบกลับ
  assert.strictEqual(typeof body.id, 'number', 'id should be a number');
  assert.strictEqual(body.id, 101, 'id should match the requested user');
  assert.ok(body.name, 'response should include a name');
  assert.ok(Array.isArray(body.roles), 'roles should be an array');
}

testGetUser().then(
  () => console.log('API test passed'),
  (err) => { console.error('API test failed:', err.message); process.exitCode = 1; }
);

รูปแบบนี้ใช้ได้และสอนหลักการพื้นฐานได้ดี แต่สำหรับชุดทดสอบ API ที่แท้จริง คุณจะต้องมีการรันที่เป็นระบบ การลองใหม่ การจัดการสภาพแวดล้อม และการรายงานที่ assert แบบดิบๆ ไม่มีให้ คู่มือของเราเกี่ยวกับ วิธีการเขียนสคริปต์ทดสอบอัตโนมัติ และ เฟรมเวิร์กการทำงานอัตโนมัติของ API ของ pytest ครอบคลุมขั้นตอนถัดไปนั้น

หากคุณไม่ต้องการสร้างชุดทดสอบด้วยตัวเอง Apidog ช่วยให้คุณสามารถกำหนดคำขอ API และแนบการยืนยันด้วยภาพ (visual assertions) บนสถานะโค้ด, ส่วนหัว และฟิลด์ JSON โดยไม่ต้องเขียนโค้ดการยืนยันเลย คุณสามารถเชื่อมโยงคำขอเป็นสถานการณ์ทดสอบอัตโนมัติ รันใน CI/CD และยังคงสามารถใช้สคริปต์ที่กำหนดเองได้เมื่อคุณต้องการการควบคุมที่ assert ให้คุณได้ นี่เป็นเส้นทางที่เร็วกว่าจาก "ฉันมี endpoint" ไปสู่ "ฉันมีชุดทดสอบ" และคุณสามารถ ดาวน์โหลด Apidog และใช้งานได้ฟรี เมื่อใช้ร่วมกับ Apidog โมดูล assert ของ Node.js ครอบคลุมทั้งการตรวจสอบด่วนและชุดทดสอบที่สมบูรณ์

คำถามที่พบบ่อย

ฉันจำเป็นต้องติดตั้งโมดูล assert หรือไม่?

ไม่จำเป็น assert ถูกสร้างมาพร้อมกับ Node.js คุณนำเข้าได้ด้วย require('node:assert/strict') หรือ require('node:assert') ไม่มีแพ็กเกจ npm ที่ต้องติดตั้งและไม่มี dependency ที่ต้องจัดการ คำนำหน้า node: ทำให้ชัดเจนว่าคุณกำลังโหลดโมดูลหลัก

อะไรคือความแตกต่างระหว่าง assert.equal และ assert.strictEqual?

ในโหมด legacy assert.equal ใช้การเปรียบเทียบแบบหลวมๆ (==) และ assert.strictEqual ใช้การเปรียบเทียบแบบเข้มงวด (===) ในโหมด strict ที่โหลดผ่าน node:assert/strict assert.equal ทำงานเหมือนกับ assert.strictEqual ทุกประการ ควรใช้โหมด strict เสมอ เพื่อไม่ให้การแปลงชนิดข้อมูลแอบผ่านการทดสอบไปอย่างเงียบๆ

เมื่อไหร่ที่ฉันควรใช้ deepStrictEqual แทน strictEqual?

ใช้ strictEqual สำหรับค่าดั้งเดิม (primitives): ตัวเลข, สตริง, บูลีน ใช้ deepStrictEqual สำหรับอ็อบเจกต์และอาร์เรย์ เพราะ strictEqual เปรียบเทียบการอ้างอิง และอ็อบเจกต์สองตัวที่แยกกันจะไม่เท่ากันในการอ้างอิง เวลาใดก็ตามที่คุณยืนยันเนื้อหา JSON หรืออ็อบเจกต์ที่ส่งคืน ให้เลือกใช้ deepStrictEqual

ฉันควรใช้โมดูล assert หรือเฟรมเวิร์กทดสอบอย่าง Jest?

สำหรับสคริปต์ด่วนและการเรียนรู้ assert แบบดิบก็ใช้ได้ สำหรับชุดทดสอบจริง ให้ใช้เฟรมเวิร์ก Node.js ยังมีตัวรันการทดสอบในตัวคือ node:test ซึ่งทำงานร่วมกับ assert ได้อย่างเป็นธรรมชาติและให้การจัดระเบียบการทดสอบ การรายงาน และความขนานโดยไม่ต้องพึ่งพา dependency ภายนอก

ฉันจะยืนยันว่าฟังก์ชัน async ปฏิเสธ (rejects) ได้อย่างไร?

ใช้ assert.rejects และอย่าลืม await มัน ส่ง Promise หรือการเรียกฟังก์ชัน async โดยอาจมีชนิดข้อผิดพลาดที่คาดหวังหรือ regular expression สำหรับข้อความ assert.rejects(somePromise, TypeError) จะผ่านก็ต่อเมื่อ Promise ถูกปฏิเสธด้วย TypeError หากไม่มี await ความล้มเหลวจะกลายเป็นการปฏิเสธที่ไม่ได้จัดการ (unhandled rejection) แทนที่จะเป็นข้อผิดพลาดการยืนยันที่ชัดเจน

ฝึกการออกแบบ API แบบ Design-first ใน Apidog

ค้นพบวิธีที่ง่ายขึ้นในการสร้างและใช้ API