Kullandığınız her test framework'ü, ister Jest, ister Mocha, ister node:test olsun, basit bir fikre dayanır: ne beklediğinizi belirtin, sonra gerçeklik bu beklentiyle uyuşmuyorsa bir hata fırlatın. Node.js, bu fikri assert adında yerleşik bir modül olarak sunar. Kurulum yok, bağımlılık yok, sadece require edin ve varsayımları kontrol etmeye başlayın.
assert modülü başlı başına öğrenmeye değerdir. Betiklerde hızlı sağlık kontrollerini sağlar, birçok test çalıştırıcısının temelini oluşturur ve herhangi bir framework onu süslemeden önce bir doğrulamanın (assertion) ne olduğunu size öğretir. Bu kılavuz, önemli yöntemleri, insanları zorlayan katı-mod vs. eski-mod ayrımını, hatalar ve asenkron kod üzerinde nasıl doğrulama yapılacağını ve aynı modülün API yanıtlarını nasıl doğrulamanıza yardımcı olduğunu kapsar.
Assert modülü ne yapar
Bir doğrulama (assertion), programınızın doğru kabul edilmesi için doğru olması gereken bir ifadedir. assert.strictEqual(total, 100) yazdığınızda, total değerinin 100'e eşit olması gerektiğini beyan ediyorsunuz. Eğer öyleyse, hiçbir şey olmaz ve yürütme devam eder. Eğer öyle değilse, assert yürütmeyi durduran ve neyin yanlış gittiğini size bildiren bir AssertionError fırlatır.
Modülü içe aktarın. Modern, önerilen biçim katı sürümdür:
const assert = require('node:assert/strict');
// veya ES modülleri ile:
// import assert from 'node:assert/strict';
En basit doğrulama, bir değerin 'truthy' olup olmadığını kontrol eder:
const user = getUser(42);
assert(user, 'getUser bir kullanıcı nesnesi döndürmeli');
İlk argüman test edilen değerdir. İkinci, isteğe bağlı argüman ise doğrulama başarısız olduğunda gösterilen bir mesajdır. Bu mesajı her zaman yazın. “getUser bir kullanıcı nesnesi döndürmeli” diyen bir hata, çıplak bir AssertionError'dan çok daha kullanışlıdır. Doğrulamaları anlamak, bir test aracında özel API doğrulamalarına geçtiğinizde de yardımcı olur.
Katı mod ve eski mod
Bu, doğru anlamanız gereken en önemli tek şeydir. assert modülünün iki modu vardır.
require('node:assert') ile elde ettiğiniz eski mod, assert.equal ve assert.deepEqual için gevşek eşitlik (==) kullanır. Bu, assert.equal(1, '1') ifadesinin geçtiği anlamına gelir, çünkü JavaScript'te 1 == '1' doğrudur. Gevşek eşitlik, iyi bilinen bir hata kaynağıdır.
require('node:assert/strict') ile elde ettiğiniz katı mod, her şey için katı eşitlik (===) kullanır. assert.equal(1, '1') beklendiği gibi başarısız olur, çünkü türler farklıdır.
const looseAssert = require('node:assert');
looseAssert.equal(1, '1'); // geçer, şaşırtıcı ve tehlikeli
const strict = require('node:assert/strict');
strict.equal(1, '1'); // AssertionError fırlatır, doğru
Katı modu kullanın. Testlerde gevşek eşitliği kabul etmek için iyi bir neden yoktur. Bu kılavuzun geri kalanı, assert.equal'ın assert.strictEqual gibi davrandığı node:assert/strict'i varsaymaktadır.
Değerleri karşılaştırma: equal ve strictEqual
assert.strictEqual(actual, expected), iki değerin === ile aynı olup olmadığını kontrol eder. Sayılar, dizeler ve boolean'lar gibi ilkel türler için ana işlevdir.
const assert = require('node:assert/strict');
function priceWithTax(price, rate) {
return price + price * rate;
}
assert.strictEqual(priceWithTax(100, 0.08), 108, 'vergi hesaplaması yüzde 8 eklemeli');
assert.strictEqual(typeof priceWithTax(100, 0.08), 'number', 'sonuç bir sayı olmalı');
İki değerin aynı olmadığı durumlarda geçen assert.notStrictEqual da vardır. Bir değerin değiştiğini doğrulamak için kullanın:
const before = getCacheKey();
refreshCache();
const after = getCacheKey();
assert.notStrictEqual(before, after, 'önbellek anahtarı yenilemeden sonra değişmeli');
Nesneler ve diziler için strictEqual yardımcı olmaz. Aynı içeriğe sahip iki nesne değişmez referanslardır, bu yüzden === false döner. Derin eşitlik bunun içindir.
Nesneleri karşılaştırma: deepStrictEqual
assert.deepStrictEqual(actual, expected), yapıyı ve değerleri özyinelemeli olarak karşılaştırır. Her anahtarın kesinlikle eşit bir değer tutması durumunda, en derine kadar, iki nesne geçerli sayılır.
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' },
'sipariş nesnesi beklenen şekle uymalı'
);
Bu, nesne döndüren fonksiyonları test ederken ve özellikle JSON gövdeleri nesne olduğu için API yanıtlarını test ederken en çok kullanacağınız yöntemdir. Karşıtı olan assert.notDeepStrictEqual, yapılar farklı olduğunda geçerli sayılır.
Bir uyarı: deepStrictEqual türleri de kontrol eder. 7 sayısını tutan bir özellik, '7' dizesini tutan bir özellikle eşleşmez. Bu katılık bir özelliktir; verilerinizdeki tür kaymasını yakalar. Birçok girdi kombinasyonu olan fonksiyonları test ediyorsanız, CSV ve JSON ile veri odaklı test kılavuzumuz, doğrulamaları veri kümeleri genelinde nasıl ölçeklendireceğinizi gösterir.
deepStrictEqual başarısız olduğunda, Node tam olarak hangi özelliklerin uyuşmadığını vurgulayan bir fark (diff) yazdırır. Bu fark, modülün en kullanışlı özelliklerinden biridir. İki büyük nesneye bakıp farkı bulmaya çalışmak yerine, birkaç vurgulanmış satırı okursunuz. İç içe geçmiş veriler için, bu durum bile deepStrictEqual'ı strictEqual ile her alanı manuel olarak kontrol etmeye tercih etmeyi haklı çıkarır.
assert.match ve assert.ok ile kısmi eşleştirme
Her kontrol tam eşitlik gerektirmez. Bazen sadece bir değerin kabaca doğru göründüğünü önemsersiniz. assert.ok(value), değer 'truthy' olduğu sürece geçerlidir, bu da “bu mevcut olmalı” kontrolleri için doğru araçtır: boş olmayan bir dize, tanımlı bir nesne, sıfır olmayan bir sayı.
assert.match(string, regexp) bir dizenin bir düzenli ifadeyle eşleşip eşleşmediğini kontrol eder ve assert.doesNotMatch tersini kontrol eder. Bunlar, tam içeriği değişen ancak şekli sabit olan değerler için kullanışlıdır.
const assert = require('node:assert/strict');
function generateOrderId() {
return 'ORD-' + Date.now();
}
const id = generateOrderId();
// tam zaman damgası değişir, bu yüzden değeri değil, biçimi doğrulayın
assert.match(id, /^ORD-\d+$/, 'sipariş kimliği ORD- ve ardından rakamlardan oluşmalı');
assert.ok(id.length > 4, 'sipariş kimliği boş olmamalı');
Bu desen özellikle API testleri için önemlidir, çünkü yanıtlar zaman damgaları, üretilen kimlikler ve tahmin edemediğiniz jetonlar içerir. Biçimi match ile, varlığını ok ile doğrularsınız ve strictEqual'ı gerçekten kontrol ettiğiniz değerler için saklarsınız.
Kodun hata fırlattığını doğrulama
Bazen doğru davranış, bir hata fırlatmak anlamına gelir. assert.throws(fn, expectedError) bir fonksiyonu çalıştırır ve yalnızca hata fırlatırsa geçerli sayılır.
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;
}
// geçerli: geçersiz girdi bir RangeError fırlatmalı
assert.throws(
() => parsePort('70000'),
RangeError,
'aralık dışı bağlantı noktası RangeError fırlatmalı'
);
// hata mesajını bir regex ile de eşleştirebilirsiniz
assert.throws(
() => parsePort('abc'),
/bir tamsayı olmalı/,
'sayısal olmayan bağlantı noktası açıklayıcı bir hata fırlatmalı'
);
// geçerli: geçerli girdi hata fırlatmamalı
assert.doesNotThrow(
() => parsePort('8080'),
'geçerli bir bağlantı noktası hata fırlatmamalı'
);
Bir fonksiyonu geçirdiğinizi, bir çağrıyı değil. assert.throws(parsePort('70000')) ifadesi, assert onu görmeden önce parsePort'u çalıştırır ve hata yakalanmadan kaçardı. Her zaman sarmalayın: () => parsePort('70000').
Asenkron kod üzerinde doğrulama: rejects
Modern Node.js kodu vaatlerle (promises) doludur ve reddedilen bir vaat, fırlatılan bir hatanın asenkron karşılığıdır. assert.rejects ve assert.doesNotReject bu durumu ele alır. Her ikisi de vaat döndürür, bu yüzden onları await etmelisiniz.
const assert = require('node:assert/strict');
async function fetchUser(id) {
if (typeof id !== 'number') {
throw new TypeError('id must be a number');
}
// ... gerçek arama burada olacaktı
return { id, name: 'Dana Lee' };
}
async function runTests() {
// geçerli: hatalı girdi bir TypeError ile reddeder
await assert.rejects(
fetchUser('sayı-değil'),
TypeError,
'dize kimliği reddetmeli'
);
// geçerli: doğru girdi reddetmeden çözümlenir
await assert.doesNotReject(
fetchUser(101),
'geçerli kimlik temiz bir şekilde çözümlenmeli'
);
}
runTests();
assert.rejects çağrısını await etmeyi unutmak yaygın bir hatadır. await olmadan, test fonksiyonu doğrulama tamamlanmadan biter ve bir hata, açık bir test hatası yerine işlenmemiş bir reddedilmeye dönüşür.
API yanıtlarını test etmek için assert kullanımı
assert modülü, bir HTTP isteğinin çıktısını kontrol etmek için gerçekten kullanışlıdır. Bir uç noktayı getirdikten sonra, bir durum kodunuz ve bir JSON gövdeniz olur ve her ikisi de doğrulanması gereken şeylerdir.
const assert = require('node:assert/strict');
async function testGetUser() {
const res = await fetch('https://api.example.com/users/101');
// durum kodunu kontrol et
assert.strictEqual(res.status, 200, 'GET /users/101, 200 döndürmeli');
const body = await res.json();
// yanıtın şeklini ve türlerini kontrol et
assert.strictEqual(typeof body.id, 'number', 'kimlik bir sayı olmalı');
assert.strictEqual(body.id, 101, 'kimlik istenen kullanıcıyla eşleşmeli');
assert.ok(body.name, 'yanıt bir isim içermeli');
assert.ok(Array.isArray(body.roles), 'roller bir dizi olmalı');
}
testGetUser().then(
() => console.log('API testi geçti'),
(err) => { console.error('API testi başarısız oldu:', err.message); process.exitCode = 1; }
);
Bu desen işe yarar ve temelleri öğretir. Ancak gerçek bir API test paketi için, ham assert'in sağlamadığı yapılandırılmış çalıştırmalar, yeniden denemeler, ortam yönetimi ve raporlama istersiniz. Otomatik test betikleri nasıl yazılır ve pytest API otomasyon framework'ü hakkındaki kılavuzlarımız bu bir sonraki adımı kapsar.
Eğer kendi test aracınızı (test harness) elle kurmak istemiyorsanız, Apidog, API isteklerini tanımlamanıza ve durum kodları, başlıklar ve JSON alanları üzerinde görsel doğrulamalar eklemenize, hiçbir doğrulama kodu yazmadan olanak tanır. İstekleri otomatik test senaryolarına zincirleyebilir, CI/CD'de çalıştırabilir ve yine de assert'in size verdiği kontrole ihtiyaç duyduğunuzda özel betiklere geçebilirsiniz. Bu, “Bir uç noktam var”dan “Bir test paketim var”a giden daha hızlı bir yoldur ve Apidog'u indirip ücretsiz kullanabilirsiniz. Apidog ile birlikte Node.js assert modülü hem hızlı kontrolleri hem de tam test paketlerini kapsar.
Sıkça sorulan sorular
Assert modülünü kurmam gerekiyor mu?
Hayır. assert, Node.js'e yerleşik olarak gelir. Onu require('node:assert/strict') veya require('node:assert') ile içe aktarın. Yüklenecek bir npm paketi veya yönetilecek bir bağımlılık yoktur. node: öneki, bir çekirdek modül yüklediğinizi açıkça belirtir.
assert.equal ve assert.strictEqual arasındaki fark nedir?
Eski modda, assert.equal gevşek eşitlik (==) kullanırken, assert.strictEqual katı eşitlik (===) kullanır. node:assert/strict aracılığıyla yüklenen katı modda, assert.equal, assert.strictEqual ile aynı şekilde davranır. Tür zorlamasının bir testi asla sessizce geçmemesi için her zaman katı modu kullanın.
deepStrictEqual yerine strictEqual'ı ne zaman kullanmalıyım?
İlkel türler için (number, string, boolean) strictEqual kullanın. Nesneler ve diziler için deepStrictEqual kullanın, çünkü strictEqual referansları karşılaştırır ve iki ayrı nesne asla referans-eşit olamaz. Bir JSON gövdesi veya dönen bir nesne üzerinde doğrulama yaptığınız her zaman deepStrictEqual'a başvurun.
Assert modülünü mü yoksa Jest gibi bir test framework'ünü mü kullanmalıyım?
Hızlı betikler ve öğrenme için, ham assert yeterlidir. Gerçek bir test paketi için bir framework kullanın. Node.js ayrıca, assert ile doğal bir şekilde eşleşen ve harici bir bağımlılık olmaksızın test organizasyonu, raporlama ve paralellik sağlayan yerleşik bir test çalıştırıcısı olan node:test ile birlikte gelir.
Asenkron bir fonksiyonun reddettiğini nasıl doğrularım?
assert.rejects kullanın ve onu await etmeyi unutmayın. Vaadi veya asenkron bir fonksiyon çağrısını, isteğe bağlı olarak beklenen bir hata türü veya mesaj regex'i ile geçirin. assert.rejects(somePromise, TypeError) yalnızca vaat bir TypeError ile reddedilirse geçerli sayılır. await olmadan, bir hata açık bir doğrulama hatası yerine işlenmemiş bir reddedilmeye dönüşür.
