# 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ı. - Published: 2026-06-21 - Updated: 2026-07-06 - Author: SharpSkill - Tags: vue, testing, vitest, vue-test-utils, interview - Reading time: 10 min --- 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](https://vitest.dev/guide/) ve bileşenleri mount etmek için [Vue Test Utils](https://test-utils.vuejs.org/). 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](https://vuejs.org/guide/scaling-up/testing.html) 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. ```typescript // vitest.config.ts 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. ```typescript // PriceTag.spec.ts 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. ```typescript // SearchBar.spec.ts 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ı](/blog/vue-nuxt/advanced-vue-3-composables-reusable-patterns) yazısındaki desenlerle iyi uyum sağlar. ```typescript // useCart.spec.ts 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. ## 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. ```typescript // useProducts.spec.ts 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](https://pinia.vuejs.org/cookbook/testing.html) bu yaklaşımı bileşen seviyesindeki testler için önerir. ```typescript // CheckoutButton.spec.ts 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. ```typescript // vitest.config.ts (coverage section) 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](/technologies/vue-nuxt/interview-questions/vue-testing) ç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ı](/blog/vue-nuxt/essential-vuejs-interview-questions) 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](/technologies/vue-nuxt) tamamını keşfedin. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/vue-nuxt/vue-3-testing-vitest-vue-test-utils