2026'da Vue 3 Testleri: Vitest, Vue Test Utils ve Mülakat Soruları

2026'da Vue testleri için uygulamalı bir rehber: Vitest yapılandırması, Vue Test Utils ile bileşen mount etme, composable ve Pinia store testleri, API mock'lama, kapsam ölçümü ve işe alım ekiplerinin sorduğu mülakat soruları.

2026'da Vitest ve Vue Test Utils ile Vue test iş akışı

Vue testleri, kendinden emin refactor işlemlerini kırılgan tahminlerden ayırır ve 2026'da araç zinciri iki kütüphane etrafında birleşmiş durumdadır: koşucu için Vitest ve bileşenleri mount etmek için Vue Test Utils. Bu rehber; yığının yapılandırılmasını, bileşen ve composable testlerini, bağımlılıkların mock'lanmasını ve işe alım ekiplerinin gerçekten sorduğu Vue test mülakat sorularının yanıtlanmasını adım adım ele alır.

2026'da Modern Vue Test Yığını

Vue dokümantasyonunun varsayılan önerisi; birim ve bileşen testleri için Vitest, düşük seviyeli mount API'si olarak Vue Test Utils ve uçtan uca kapsam için Playwright ya da Cypress kullanmaktır. Vitest, uygulamayla aynı Vite yapılandırmasını yeniden kullandığından testler, neredeyse anlık sıcak yeniden yüklemeyle birlikte aynı dönüşüm hattı üzerinden çalışır.

Vue 3 Projesi İçin Vitest Yapılandırması

Vitest, Vite hattını paylaşır; bu da tek bir yapılandırma dosyasının hem geliştirme sunucusunu hem de test koşucusunu yönetmesi anlamına gelir. Bileşen testlerinin render edileceği bir DOM'a sahip olması için environment seçeneği jsdom veya happy-dom olarak ayarlanmalıdır. globals: true bayrağı ise describe, it ve expect fonksiyonlarını her dosyada içe aktarmaya gerek kalmadan erişilebilir kılar.

vitest.config.tstypescript
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath } from 'node:url'

export default defineConfig({
  plugins: [vue()],
  test: {
    // jsdom provides document/window so components can mount
    environment: 'jsdom',
    // expose describe/it/expect globally
    globals: true,
    // run this before each test file (matchers, cleanup)
    setupFiles: ['./tests/setup.ts'],
    // only pick up *.spec.ts and *.test.ts files
    include: ['**/*.{test,spec}.ts'],
  },
  resolve: {
    alias: {
      // mirror the @ alias used across the app
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
})

Vitest 3 ile yukarıdaki yapılandırma; vitest, @vue/test-utils, @vitejs/plugin-vue ve jsdom paketleri kurulduktan sonra ek bir ayara gerek kalmadan çalışır. Takma ad (alias) uygulama yapılandırmasını birebir yansıttığı için @/composables/useCart gibi içe aktarmalar hem testlerde hem de üretimde aynı şekilde çözümlenir.

Vue Test Utils ile Bileşenleri Mount Etme

Vue Test Utils iki giriş noktası sunar: tüm bileşen ağacını render eden mount ve alt bileşenleri stub'layan shallowMount. Çoğu birim testi için mount tercih edilir çünkü gerçek render davranışını çalıştırır. Dönen wrapper nesnesi; render edilen çıktıya karşı doğrulama yapmak için find, get ve text gibi sorgu yardımcıları sağlar.

PriceTag.spec.tstypescript
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import PriceTag from '@/components/PriceTag.vue'

describe('PriceTag', () => {
  it('formats the amount as currency', () => {
    const wrapper = mount(PriceTag, {
      // props are passed through the mounting options
      props: { amount: 4200, currency: 'EUR' },
    })

    // get() throws if the selector is missing, unlike find()
    expect(wrapper.get('[data-test="price"]').text()).toBe('€42.00')
  })

  it('applies a discount class when on sale', () => {
    const wrapper = mount(PriceTag, {
      props: { amount: 4200, currency: 'EUR', onSale: true },
    })

    // classes() returns the array of applied CSS classes
    expect(wrapper.get('[data-test="price"]').classes()).toContain('price--sale')
  })
})

CSS sınıfları yerine data-test öznitelikleri üzerinden elemanları hedeflemek testleri dayanıklı tutar: .price--sale üzerindeki bir stil değişikliği seçiciyi bozmaz, yalnızca gerçek bir davranış değişikliği bozar. Bu ayrıştırma, bakımı kolay Vue testlerinde tekrar eden bir temadır.

Kullanıcı Etkileşimlerini ve Yayılan Olayları Test Etme

Etkileşimli bileşenler, bir tıklama ya da girdiden sonra ne olduğuna dair doğrulamalara ihtiyaç duyar. Vue Test Utils, trigger çağrısından bir promise döndürür ve bunu await etmek Vue'nun reaktivite kuyruğunu boşaltarak DOM'un güncellemeyi yansıtmasını sağlar. emitted yardımcısı ise bir bileşenin tetiklediği her özel olayı kaydeder; ebeveyn-çocuk sözleşmeleri de bu şekilde doğrulanır.

SearchBar.spec.tstypescript
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import SearchBar from '@/components/SearchBar.vue'

describe('SearchBar', () => {
  it('emits search with the typed query', async () => {
    const wrapper = mount(SearchBar)

    // setValue writes to the input and fires an input event
    await wrapper.get('input').setValue('vitest')
    // awaiting trigger flushes the reactivity queue before assertions
    await wrapper.get('[data-test="submit"]').trigger('click')

    // emitted() returns a record of every event and its payloads
    const events = wrapper.emitted('search')
    expect(events).toHaveLength(1)
    // events[0] is the first emission, [0] its first argument
    expect(events![0][0]).toBe('vitest')
  })
})
DOM Güncellemelerini Her Zaman Await Edin

Vue, reaktif güncellemeleri asenkron olarak toplu halde işler. Bir trigger ya da setValue çağrısını await etmeyi unutmak, kırılgan Vue testlerinin en yaygın nedenidir: doğrulamalar DOM yeniden render edilmeden önce çalışır ve bu yüzden eski çıktıyı okur. Bir durum değişikliği olay yardımcılarının dışında gerçekleştiğinde, vue içinden nextTick içe aktarılmalı ve doğrulamadan önce await nextTick() çağrılmalıdır.

Vue Composable'larını İzole Şekilde Test Etme

Yalnızca reaktivite API'lerini (ref, computed, watch) kullanan composable'lar hiçbir bileşene ihtiyaç duymaz: bunlar reaktif durum döndüren düz fonksiyonlardır, dolayısıyla doğrudan çağırıp .value üzerinden doğrulama yapmak yeterlidir. Bu, iş mantığını kapsamanın en hızlı ve en odaklı yoludur ve gelişmiş Vue 3 composable'ları yazısındaki desenlerle iyi uyum sağlar.

useCart.spec.tstypescript
import { describe, it, expect } from 'vitest'
import { useCart } from '@/composables/useCart'

describe('useCart', () => {
  it('tracks total price as items change', () => {
    // composables using only ref/computed run without mounting
    const { items, total, addItem } = useCart()

    expect(total.value).toBe(0)

    addItem({ id: 1, price: 1500, qty: 2 })
    // computed total recalculates synchronously on state change
    expect(total.value).toBe(3000)

    addItem({ id: 2, price: 500, qty: 1 })
    expect(items.value).toHaveLength(2)
    expect(total.value).toBe(3500)
  })
})

onMounted gibi yaşam döngüsü kancalarına bağımlı olan composable'lar bir istisnadır: bunların bir bileşen örneği içinde çalışması gerekir. Yaygın çözüm, setup içinde composable'ı çağıran ve sonucu dışarı açan küçük bir yardımcı bileşen oluşturmak, ardından bu yardımcıyı Vue Test Utils ile mount etmektir.

Vue.js / Nuxt.js mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

vi.mock ile API Çağrılarını Mock'lama

Gerçek ağ istekleri testleri yavaş ve belirsiz hale getirir. Vitest, vi.mock ile modülleri değiştirir ve vi.fn ile casus (spy) fonksiyonlar oluşturur. Aşağıdaki desen, fetch çağrısını saran modülü mock'lar; böylece test edilen composable, bir sunucuya hiç dokunmadan kontrollü veri alır.

useProducts.spec.tstypescript
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { useProducts } from '@/composables/useProducts'
import { getProducts } from '@/api/products'

// replace the whole module with mocked exports
vi.mock('@/api/products', () => ({
  getProducts: vi.fn(),
}))

describe('useProducts', () => {
  beforeEach(() => {
    // reset call history between tests to avoid leakage
    vi.mocked(getProducts).mockReset()
  })

  it('exposes fetched products and clears loading', async () => {
    // define what the mocked API returns for this test
    vi.mocked(getProducts).mockResolvedValue([
      { id: 1, name: 'Keyboard' },
    ])

    const { products, loading, load } = useProducts()
    await load()

    expect(getProducts).toHaveBeenCalledOnce()
    expect(loading.value).toBe(false)
    expect(products.value[0].name).toBe('Keyboard')
  })
})

Modül sınırında mock'lamak, composable'ın iç mantığına dokunmadan bırakırken her teste API yanıtı üzerinde tam kontrol verir; hata yolları da buna dahildir. Bunun yerine mockRejectedValue çağrmak, tek bir testin hataların bir hata durumu ayarlayıp yükleme göstergesini durdurduğunu doğrulamasına olanak tanır.

2026'da Pinia Store Testleri

Store'lar bileşenler arası durumu tutar ve resmi @pinia/testing paketi bunların test edilmesini kolaylaştırır. createTestingPinia, varsayılan olarak her eylemi (action) stub'lar; böylece bir bileşen testi, yan etkilerini çalıştırmadan bir eylemin gönderildiğini doğrulayabilir. Pinia test rehberi bu yaklaşımı bileşen seviyesindeki testler için önerir.

CheckoutButton.spec.tstypescript
import { describe, it, expect, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
import CheckoutButton from '@/components/CheckoutButton.vue'
import { useCartStore } from '@/stores/cart'

describe('CheckoutButton', () => {
  it('dispatches checkout on click', async () => {
    const wrapper = mount(CheckoutButton, {
      global: {
        plugins: [
          // vi.fn spies on actions instead of executing them
          createTestingPinia({ createSpy: vi.fn }),
        ],
      },
    })

    const store = useCartStore()
    await wrapper.get('[data-test="checkout"]').trigger('click')

    // the action is stubbed, so only the dispatch is asserted
    expect(store.checkout).toHaveBeenCalledOnce()
  })
})

Bileşen entegrasyonu yerine store mantığının kendisini test etmek için stubActions: false geçin; böylece eylemler normal şekilde çalışır ve ardından ortaya çıkan durum üzerinde doğrulama yapılır. Stub'lanmış eylemli bileşen testleri ile gerçek eylemli store testleri arasındaki bu ayrım, her test paketini tek bir sorumluluğa odaklı tutar.

Watch Modunda Test Çalıştırma ve Kapsam Ölçme

Vitest, kaydedilen bir dosyadan etkilenen yalnızca ilgili testleri yeniden çalıştıran bir watch modu sunar; bu da geliştirme sırasındaki geri bildirim döngüsünü saniyenin küçük bir kesrine indirir. Kapsam raporlama, @vitest/coverage-v8 sağlayıcısı aracılığıyla yerleşik olarak gelir ve başarısız bir testin ya da bir kapsam gerilemesinin birleştirmeyi engelleyebildiği sürekli entegrasyon hattına sorunsuzca entegre olur.

vitest.config.ts (coverage section)typescript
export default defineConfig({
  test: {
    coverage: {
      // v8 is the fastest provider and needs no instrumentation step
      provider: 'v8',
      reporter: ['text', 'html', 'lcov'],
      // fail CI when a threshold drops below the target
      thresholds: {
        statements: 80,
        branches: 75,
        functions: 80,
      },
      // exclude generated and config files from the report
      exclude: ['**/*.config.ts', '**/types/**'],
    },
  },
})

Tek başına vitest çalıştırmak yerelde watch modunu başlatırken, vitest run --coverage CI'a uygun tek geçişli bir koşu yürütür. Açık eşikler belirlemek, kapsamı bir gösteriş metriğinden zorunlu bir kalite kapısına dönüştürür: dal (branch) kapsamını yüzde 75'in altına düşüren bir pull request otomatik olarak başarısız olur ve bu da katkıda bulunanları yalnızca mutlu yolu değil, ekledikleri yolları da test etmeye yönlendirir.

Sık Sorulan Vue Test Mülakat Soruları ve Yanıtları

Test soruları çoğu kıdemli Vue mülakatında karşımıza çıkar çünkü bir adayın bakım kolaylığı hakkında nasıl düşündüğünü ortaya koyar. Aşağıdaki yanıtlar en sık gündeme gelen kavramları kapsar ve tamamı Vue test mülakat modülünde çalışılır.

shallowMount, mount yerine ne zaman kullanılmalı? Bir bileşen ağır ya da halihazırda test edilmiş çocuklar render ettiğinde ve test yalnızca ebeveynin kendi mantığıyla ilgilendiğinde shallowMount tercih edilir. Çocukları stub'lamak birimi izole eder ve render'ı hızlandırır; bunun bedeli, bileşenler arası gerçek entegrasyonun doğrulanmamasıdır.

Vue Test Utils'te asenkron güncellemeler nasıl ele alınır? Vue, reaktif değişiklikleri bir sonraki tick'te uygular. trigger ve setValue gibi olay yardımcıları, DOM güncellendikten sonra çözümlenen promise'ler döndürür; dolayısıyla bunları await etmek yeterlidir. Bu yardımcıların dışında değişen durum için await nextTick(), doğrulamalar çalışmadan önce kuyruğu boşaltmaya zorlar.

find ile get arasındaki fark nedir? find, hiçbir eleman eşleşmediğinde boş bir wrapper döndürür ve asla hata fırlatmaz; bu da expect(wrapper.find('.error').exists()).toBe(false) gibi doğrulamalara uygundur. get, eksik bir elemanda anında hata fırlatır ve elemanın var olması beklendiğinde, yokluğunun gerçek bir başarısızlık sayıldığı durumlarda daha iyi bir seçim olur.

data-test öznitelikleri neden sınıf seçicilerine tercih edilir? Sınıf adları stil ve yapı ile değişir; bu yüzden onları sorgulayan testler kozmetik düzenlemelerde bozulur. Ayrılmış bir data-test kancası test niyetini açıkça ifade eder, refactor'ları atlatır ve yanlış negatifleri azaltır.

onMounted üzerine dayanan bir composable nasıl test edilir? Yaşam döngüsü kancaları yalnızca bir bileşen örneği içinde tetiklenir, dolayısıyla composable doğrudan çağrılamaz. Standart teknik; composable'ı setup içinde çağıran ve dönüş değerini dışarı açan tek kullanımlık bir sarmalayıcı bileşen, ardından bu sarmalayıcıyı Vue Test Utils ile mount edip wrapper üzerinden doğrulama yapmaktır. Bu, test edilen mantığı izole ederken reaktivite ve yaşam döngüsü bağlantılarını sağlam tutar. Daha fazla kavramsal ve kodlama sorusu temel Vue.js mülakat soruları rehberinde toplanmıştır.

Sonuç

2026'da güvenilir bir Vue test kurulumu birkaç bilinçli tercihe dayanır:

  • Testlerin uygulamanın tam Vite dönüşüm hattını paylaşması için Vitest'i environment: 'jsdom' ve Vue eklentisiyle çalıştırın.
  • Bir alt bileşen ağır olmadıkça ya da başka bir yerde zaten kapsanmadıkça shallowMount yerine mount tercih edin.
  • Kırılgan, zamanlamaya bağlı testleri ortadan kaldırmak için doğrulamadan önce trigger, setValue ve nextTick çağrılarını her zaman await edin.
  • Yalnızca reaktivite API'lerini kullanan composable'ları doğrudan çağırıp .value üzerinden doğrulayarak test edin.
  • Ağ davranışını belirli ve hata yollarını test edilebilir kılmak için modül sınırında vi.mock ile mock'layın.
  • Bileşen testleri için createTestingPinia({ createSpy: vi.fn }), store mantığını çalıştırırken ise stubActions: false kullanın.
  • Testlerin yalnızca gerçek davranış değişikliklerinde bozulup asla stilde bozulmaması için elemanları data-test öznitelikleri üzerinden sorgulayın.

Bu desenlere hakim olun; test etmek bir angarya olmaktan çıkar, gerilemeleri üretime ulaşmadan yakalayan bir tasarım aracına dönüşür. Mülakata hazır beceriler geliştirmeye devam etmek için Vue ve Nuxt öğrenme yolunun tamamını keşfedin.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Etiketler

#vue
#testing
#vitest
#vue-test-utils
#interview

Paylaş

İlgili makaleler