Node.js İle Unit Test Yazımı İçin Jest Entegrasyonu Nasıl Yapılır?

Node.js İle Unit Test Yazımı İçin Jest Entegrasyonu Nasıl Yapılır?
Node.js İle Unit Test Yazımı İçin Jest Entegrasyonu Nasıl Yapılır?

Ön Hazırlık ve Ortam Kurulumu

Jest entegrasyonuna başlamadan önce sisteminizde Node.js'in güncel bir sürümünün (LTS sürümü önerilir) yüklü olduğundan emin olmalısınız. İlk adım olarak proje dizininizi oluşturun ve gerekli paketleri yükleyin.

# Proje dizinini oluşturun
mkdir node-jest-projesi
cd node-jest-projesi

# Projeyi başlatın
npm init -y

# Jest kütüphanesini geliştirme bağımlılığı olarak kurun
npm install --save-dev jest

Burada --save-dev parametresini kullanmamızın sebebi, Jest'in sadece geliştirme ve test ortamında gerekli olması, üretim (production) ortamında kod paketine dahil edilmesine gerek olmamasıdır. Bu, uygulamanızın boyutunu optimize eder.

Jest Yapılandırması ve Test Senaryosu Oluşturma

Jest'i projenize dahil ettikten sonra, testlerinizi çalıştırmak için package.json dosyanızda bir düzenleme yapmanız gerekir. Bu adım, test komutlarını terminal üzerinden kolayca yönetmenizi sağlar.

{
  "scripts": {
    "test": "jest"
  }
}

Ardından, basit bir toplama işlemi yapan fonksiyonumuzu yazalım ve bunu test edelim. math.js adında bir dosya oluşturun:

// math.js
function topla(a, b) {
  return a + b;
}
module.exports = topla;

Bu fonksiyonun doğru çalışıp çalışmadığını test etmek için math.test.js dosyasını oluşturacağız. Jest, .test.js uzantılı dosyaları otomatik olarak algılar.

Adım Adım İlk Unit Testi Yazma

Test dosyanızda, fonksiyonunuzu import ederek beklenen sonuçları (assertion) tanımlayacağız. Jest'in sunduğu test bloğu ve expect fonksiyonu, test yazımının temelini oluşturur.

// math.test.js
const topla = require('./math');

test('İki sayının toplamı doğru hesaplanmalı', () => {
  expect(topla(2, 3)).toBe(5);
});

Testi çalıştırmak için terminalde npm test komutunu girin. Jest, math.test.js dosyasını bulacak ve içerisindeki testleri çalıştırarak sonucu size raporlayacaktır. Başarılı bir test, yeşil bir onay işareti ile gösterilir.

Jest ile Mocking ve Bağımlılık Yönetimi

Gerçek dünya uygulamalarında fonksiyonlar genellikle veritabanı veya API istekleri gibi dış bağımlılıklara sahiptir. Bu dış bağımlılıkları test etmek yerine, Jest ile bunları "mock"layarak (taklit ederek) izole bir test ortamı yaratırız.

// api.js
const axios = require('axios');

async function veriGetir() {
  const response = await axios.get('https://api.ornek.com/veri');
  return response.data;
}
module.exports = veriGetir;

Bu fonksiyonu test ederken gerçek bir API çağrısı yapmamak için axios kütüphanesini mock'lamalıyız:

// api.test.js
const veriGetir = require('./api');
const axios = require('axios');

jest.mock('axios');

test('API verisi başarıyla çekilmeli', async () => {
  const mockVeri = { data: 'Test Verisi' };
  axios.get.mockResolvedValue(mockVeri);

  const sonuc = await veriGetir();
  expect(sonuc).toBe('Test Verisi');
});

Kritik Uyarı: Mocking kullanırken, gerçek dış dünya etkileşimlerini (örneğin veritabanı yazma işlemleri) testin içine dahil etmeyin. Bu, testlerin yavaşlamasına ve hata payının artmasına neden olur. Her zaman izole birimler üzerinde çalışın.

Test Yöntemlerinin Karşılaştırılması

Unit test yazarken kullanılan farklı yaklaşımları aşağıdaki tabloda inceleyebilirsiniz:

Yöntem Avantajı Dezavantajı
Unit Test Hızlı, izole, hata kaynağını bulmak kolay. Entegrasyon hatalarını yakalayamaz.
Integration Test Modüllerin uyumunu test eder. Kurulumu ve yönetimi daha karmaşıktır.
E2E Test Kullanıcı deneyimini simüle eder. Çok yavaştır, bakımı zordur.

Güvenlik ve En İyi Uygulamalar

Yazılım geliştirme sürecinde testler, kodunuzun güvenliğini doğrulamak için de kullanılmalıdır. Özellikle kullanıcı girdilerini işleyen fonksiyonlarda, "edge case" (uç durum) testleri yazmak, güvenlik açıklarını erkenden fark etmenizi sağlar.

// validator.js
function guvenliMi(input) {
  return typeof input === 'string' && input.length > 0;
}
module.exports = guvenliMi;

// validator.test.js
const guvenliMi = require('./validator');

test('Boş girdi güvenlik hatası döndürmeli', () => {
  expect(guvenliMi('')).toBe(false);
});

Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Uygulamalarınızda SQL Injection, XSS gibi saldırılara karşı korunmak için her zaman güncel kütüphaneler kullanın ve kullanıcı girdilerini asla doğrudan çalıştırmayın.

Sıkça Sorulan Sorular

Jest neden diğer test kütüphanelerine göre tercih ediliyor?

Jest, "sıfır yapılandırma" felsefesiyle gelir. Test çalıştırıcı, assertion kütüphanesi ve mock araçları tek bir paket içinde sunulduğu için ek kurulumlarla uğraşmazsınız.

Test dosyalarımı nereye koymalıyım?

Projenizde __tests__ klasörü oluşturabilir veya test edeceğiniz dosyanın yanına dosyaAdı.test.js şeklinde ekleyebilirsiniz. İkinci yöntem, dosya takibini kolaylaştırdığı için daha yaygındır.

Async/Await fonksiyonları nasıl test edilir?

Jest, async fonksiyonları doğal olarak destekler. Test fonksiyonunuzun başına async ekleyip, await expect(...).resolves.toBe(...) sözdizimini kullanabilirsiniz.

Kod kapsamı (Code Coverage) nedir?

Kod kapsamı, yazdığınız testlerin projenizdeki kodun yüzde kaçını kapsadığını gösteren bir metriktir. jest --coverage komutu ile bunu raporlayabilirsiniz.

Jest ile veritabanı test edilir mi?

Evet, ancak veritabanı testleri için "in-memory" (bellek içi) veritabanı çözümleri kullanmanız önerilir. Bu sayede testleriniz gerçek veritabanı sunucusuna ihtiyaç duymadan hızlıca çalışır.

Jest Testlerinde Hata Ayıklama (Debugging) Stratejileri

Testleriniz beklediğiniz gibi çalışmadığında veya karmaşık bir mantık hatasıyla karşılaştığınızda, console.log kullanmak yerine Jest'in sunduğu profesyonel hata ayıklama araçlarını kullanmak süreci ciddi oranda hızlandırır. Node.js'in yerleşik hata ayıklayıcısını Jest ile entegre ederek kodunuzu adım adım inceleyebilirsiniz.

VS Code ile Debugging

Visual Studio Code kullanıyorsanız, .vscode/launch.json dosyanıza aşağıdaki yapılandırmayı ekleyerek testlerinizi doğrudan IDE üzerinden "breakpoint" koyarak çalıştırabilirsiniz:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Jest Debug",
      "program": "${workspaceFolder}/node_modules/jest/bin/jest.js",
      "args": ["--runInBand"],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "disableOptimisticBPs": true
    }
  ]
}

Bu yapılandırma ile --runInBand bayrağını kullanarak testlerin tek bir işlemci çekirdeğinde ve sırayla çalışmasını sağlarsınız; bu da breakpoint'lerin tetiklenmesi için kritik bir öneme sahiptir.

Jest Testlerinde Performans Optimizasyonu

Projeniz büyüdükçe test dosyalarınızın sayısı artacak ve bu da CI/CD süreçlerinde darboğazlara yol açabilecektir. Jest, varsayılan olarak tüm testleri paralel çalıştırır ancak bazı durumlarda bu durum kaynak tüketimini aşırı artırabilir.

Test Çalıştırma Süresini Kısaltma Yöntemleri

  • --findRelatedTests: Sadece değiştirdiğiniz dosya ile ilişkili testleri çalıştırarak zaman kazanın: jest --findRelatedTests path/to/file.js
  • --maxWorkers: İşlemci kaynaklarını sınırlayın. Örneğin, CI ortamında --maxWorkers=50% kullanarak sistemin kilitlenmesini önleyebilirsiniz.
  • --onlyChanged: Sadece son commit'ten sonra değişen dosyalarla ilgili testleri çalıştırın.

Aşağıdaki tablo, test performansını etkileyen temel Jest yapılandırma parametrelerini özetlemektedir:

Parametre Açıklama Kullanım Alanı
--runInBand Testleri tek süreçte çalıştırır. Hata ayıklama ve CI ortamları.
--bail İlk hata alındığında testi durdurur. Hızlı geri bildirim döngüsü.
--detectOpenHandles Kapatılmamış veritabanı veya ağ bağlantılarını bulur. Bellek sızıntılarını giderme.

Testlerinizde --detectOpenHandles bayrağını kullanmak, özellikle asenkron işlemlerde bağlantıların açık kalması nedeniyle testlerin "asılı kalması" sorununu çözmek için en etkili yöntemdir. Bu komut, Jest'e hangi işlemin testin bitmesini engellediğini rapor etme talimatı verir.

Sonuç

Node.js projelerinizde Jest entegrasyonu yapmak, kodunuzun güvenilirliğini artırmanın en etkili yoludur. Bu rehberde, kurulumdan başlayarak temel test senaryolarına ve mocking tekniklerine kadar kapsamlı bir yol haritası izledik. Bir sonraki adım olarak, projenize "Continuous Integration" (Sürekli Entegrasyon) süreçlerini dahil ederek, her "push" işleminde testlerinizin otomatik olarak çalışmasını sağlayabilirsiniz. Yazılım geliştirme yolculuğunuzda test yazmayı bir alışkanlık haline getirmek, uzun vadede hata ayıklama sürenizi ciddi oranda azaltacaktır.

Bu yazıya tepkinizi paylaşın:
Deniz Aydın

On yıldır dijital yayıncılıkta pratik çözüm rehberleri hazırlıyorum. Karmaşık süreçleri herkesin anlayabileceği adım adım yönergelere dönüştürme konusunda uzmanım.

Yorumlar (0)

Yorum Yaz