Skip to content
Vitest 1
Main Navigation KılavuzAPIYapılandırmaİleri
1.6.1
0.34.6

Türkçe

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
čeština
magyar

Türkçe

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
čeština
magyar

Görünüm

Sidebar Navigation

Kılavuz

Neden Vitest

Başlangıç

Özellikler

Çalışma Alanı

Komut Satırı Arayüzü

Test Filtreleme

Raporlayıcılar

Kapsam

Anlık Görüntü (Snapshot) Testleri

Sahtecilik (Mocking)

Türleri Test Etme

Vitest Arayüzü

Tarayıcı Modu

Kaynak İçi Test

Test Bağlamı

Test Ortamı

Eşleştiricileri Genişletme

IDE Tümleştirmeleri

Hata Ayıklama

Diğer Test Çalıştırıcılarıyla Karşılaştırmalar

Geçiş Rehberi

Yaygın Hatalar

Performansı İyileştirme

API

Test API Başvurusu

Sahte Fonksiyonlar

Vi

expect

expectTypeOf

assert

assertType

Yapılandırma

Vitest Yapılandırma Dosyasını Yönetme

Vitest'in Yapılandırılması

Bu sayfada

Sahtecilik (Mocking) ​

Test yazarken, dahili veya harici bir hizmetin "sahte" bir sürümünü oluşturmanız gerekebilir. Bu işlem genellikle "mocking" (sahtecilik) olarak adlandırılır. Vitest, vi yardımcısı aracılığıyla size bu konuda yardımcı olacak işlevler sunar. import { vi } from 'vitest' ile içe aktarabilir veya küresel yapılandırma etkinleştirildiğinde global olarak erişebilirsiniz.

WARNING

Testler arasındaki sahte durum değişikliklerini önlemek için her testten önce veya sonra sahteleri temizlemeyi veya geri yüklemeyi unutmayın! Daha fazla bilgi için mockReset belgelerine bakın.

Hemen başlamak isterseniz, API bölümüne göz atın, aksi takdirde sahtecilik dünyasına daha derinlemesine dalmak için okumaya devam edin.

Tarihler ​

Bazen test sırasında tutarlılığı sağlamak için tarihin kontrolünü elinizde tutmanız gerekebilir. Vitest, zamanlayıcıları ve sistem tarihini manipüle etmek için @sinonjs/fake-timers paketini kullanır. Belirli API hakkında daha fazla ayrıntıyı burada bulabilirsiniz.

Örnek ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const businessHours = [9, 17];

function purchase() {
  const currentHour = new Date().getHours();
  const [open, close] = businessHours;

  if (currentHour > open && currentHour < close) return { message: 'Success' };

  return { message: 'Error' };
}

describe('satın alma akışı', () => {
  beforeEach(() => {
    // Vitest'e sahte zamanlayıcılar kullanacağımızı belirt
    vi.useFakeTimers();
  });

  afterEach(() => {
    // Her test çalıştırmasından sonra tarihi geri yükle
    vi.useRealTimers();
  });

  it('iş saatleri içinde satın almalara izin verir', () => {
    // İş saatleri içinde saati ayarla
    const date = new Date(2000, 1, 1, 13);
    vi.setSystemTime(date);

    // Date.now()'a erişim yukarıda ayarlanan tarihle sonuçlanacaktır
    expect(purchase()).toEqual({ message: 'Success' });
  });

  it('iş saatleri dışında satın almalara izin vermez', () => {
    // İş saatleri dışında saati ayarla
    const date = new Date(2000, 1, 1, 19);
    vi.setSystemTime(date);

    // Date.now()'a erişim yukarıda ayarlanan tarihle sonuçlanacaktır
    expect(purchase()).toEqual({ message: 'Error' });
  });
});

Fonksiyonlar ​

Fonksiyonları sahteleme iki farklı kategoriye ayrılabilir: izleme (spying) ve taklit etme (mocking).

Bazen tek ihtiyacınız olan belirli bir fonksiyonun çağrılıp çağrılmadığını (ve muhtemelen hangi argümanların geçirildiğini) doğrulamaktır. Bu durumlarda, doğrudan vi.spyOn() ile kullanabileceğimiz bir gözetleyici yeterli olacaktır (buradan daha fazla bilgi edinin).

Ancak gözetleyiciler yalnızca fonksiyonları izlemenize yardımcı olabilir, bu fonksiyonların uygulamasını değiştiremezler. Bir fonksiyonun sahte (veya taklit edilmiş) bir sürümünü oluşturmamız gerektiği durumlarda, vi.fn() kullanabiliriz (buradan daha fazla bilgi edinin).

Fonksiyonları sahteleme için bir temel olarak Tinyspy kullanıyoruz, ancak onu jest uyumlu hale getirmek için kendi sarmalayıcımız var. Hem vi.fn() hem de vi.spyOn() aynı metotları paylaşır, ancak yalnızca vi.fn()'nin dönüş sonucu çağrılabilir.

Örnek ​

js
import { afterEach, describe, expect, it, vi } from 'vitest';

function getLatest(index = messages.items.length - 1) {
  return messages.items[index];
}

const messages = {
  items: [
    { message: 'Simple test message', from: 'Testman' },
    // ...
  ],
  getLatest, // `getter` veya `setter` özellikleri destekleniyorsa kullanılabilir
};

describe('mesajları okuma', () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('bir spy ile en son mesajı almalı', () => {
    const spy = vi.spyOn(messages, 'getLatest');
    expect(spy.getMockName()).toEqual('getLatest');

    expect(messages.getLatest()).toEqual(
      messages.items[messages.items.length - 1]
    );

    expect(spy).toHaveBeenCalledTimes(1);

    spy.mockImplementationOnce(() => 'access-restricted');
    expect(messages.getLatest()).toEqual('access-restricted');

    expect(spy).toHaveBeenCalledTimes(2);
  });

  it('bir mock ile almalı', () => {
    const mock = vi.fn().mockImplementation(getLatest);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(1);

    mock.mockImplementationOnce(() => 'access-restricted');
    expect(mock()).toEqual('access-restricted');

    expect(mock).toHaveBeenCalledTimes(2);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(3);
  });
});

Daha Fazla ​

  • Jest'in Sahte Fonksiyonları

Global Değişkenler ​

vi.stubGlobal yardımcısını kullanarak jsdom veya node ile mevcut olmayan global değişkenleri sahteleştirebilirsiniz. Global değişkenin değerini bir globalThis nesnesine yerleştirecektir.

ts
import { vi } from 'vitest';

const IntersectionObserverMock = vi.fn(() => ({
  disconnect: vi.fn(),
  observe: vi.fn(),
  takeRecords: vi.fn(),
  unobserve: vi.fn(),
}));

vi.stubGlobal('IntersectionObserver', IntersectionObserverMock);

// artık `IntersectionObserver` veya `window.IntersectionObserver` olarak erişebilirsiniz

Modüller ​

Sahte modüller, bazı diğer kodlarda çağrılan üçüncü parti kütüphaneleri gözlemlemenizi ve argümanları, çıktıyı test etmenize veya hatta uygulamasını yeniden tanımlamanıza olanak tanır.

Daha ayrıntılı bir API açıklaması için vi.mock() api bölümüne bakın.

Otomatik Sahteleme Algoritması ​

Kodunuz, bu modül için herhangi bir ilişkili __mocks__ dosyası veya factory olmadan sahte bir modülü içe aktarıyorsa, Vitest modülün kendisini sahteleyecektir. Bu işlem, modülü çağırarak ve her dışa aktarmayı sahteleyerek gerçekleştirilir.

Aşağıdaki prensipler geçerlidir:

  • Tüm diziler boşaltılacaktır.
  • Tüm ilkel türler ve koleksiyonlar aynı kalacaktır.
  • Tüm nesneler derinlemesine klonlanacaktır.
  • Sınıfların tüm örnekleri ve prototipleri derinlemesine klonlanacaktır.

Sanal Modüller ​

Vitest, Vite'in sanal modüllerini taklit etmeyi destekler. Bu, sanal modüllerin Jest'te ele alınma şeklinden farklı çalışır. Bir vi.mock işlevine virtual: true geçirmek yerine, Vite'ye modülün var olduğunu söylemeniz gerekir, aksi takdirde ayrıştırma sırasında başarısız olur. Bunu birkaç şekilde yapabilirsiniz:

  1. Bir takma ad sağlayın
ts
// vitest.config.js
export default {
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
};
  1. Sanal bir modülü çözen bir eklenti sağlayın
ts
// vitest.config.js
export default {
  plugins: [
    {
      name: 'virtual-modules',
      resolveId(id) {
        if (id === '$app/forms') return 'virtual:$app/forms';
      },
    },
  ],
};

İkinci yaklaşımın avantajı, dinamik olarak farklı sanal giriş noktaları oluşturabilmenizdir. Birkaç sanal modülü tek bir dosyaya yönlendirirseniz, bunların hepsi vi.mock'tan etkilenecektir, bu nedenle benzersiz tanımlayıcılar kullandığınızdan emin olun.

Taklit Etme Tuzakları ​

Aynı dosyanın diğer yöntemleri içinde çağrılan yöntemlere yapılan çağrıları taklit etmenin mümkün olmadığına dikkat edin. Örneğin, bu kodda:

ts
export function foo() {
  return 'foo';
}

export function foobar() {
  return `${foo()}bar`;
}

foo yöntemine doğrudan referans verildiğinden, dışarıdan foo yöntemini taklit etmek mümkün değildir. Bu nedenle, bu kodun foobar içindeki foo çağrısı üzerinde hiçbir etkisi olmayacaktır (ancak diğer modüllerdeki foo çağrısını etkileyecektir):

ts
import { vi } from 'vitest';
import * as mod from './foobar.js';

// bu yalnızca orijinal modülün dışındaki "foo"yu etkileyecektir
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
  return {
    ...(await importOriginal<typeof import('./foobar.js')>()),
    // bu yalnızca orijinal modülün dışındaki "foo"yu etkileyecektir
    foo: () => 'mocked',
  };
});

Doğrudan foobar yöntemine uygulama sağlayarak bu davranışı doğrulayabilirsiniz:

ts
// foobar.test.js
import * as mod from './foobar.js';

vi.spyOn(mod, 'foo');

// dışa aktarılan foo, taklit edilen yönteme başvurur
mod.foobar(mod.foo);
ts
// foobar.js
export function foo() {
  return 'foo';
}

export function foobar(injectedFoo) {
  return injectedFoo !== foo; // false
}

Bu, amaçlanan davranıştır. Genellikle, taklit etme bu şekilde dahil olduğunda, bu kötü kodun bir işaretidir. Kodunuzu birden çok dosyaya yeniden düzenlemeyi veya bağımlılık enjeksiyonu gibi teknikler kullanarak uygulama mimarinizi geliştirmeyi düşünün.

Örnek ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { Client } from 'pg';
import { failure, success } from './handlers.js';

// işleyiciler
export function success(data) {}
export function failure(data) {}

// todoları al
export async function getTodos(event, context) {
  const client = new Client({
    // ...clientOptions
  });

  await client.connect();

  try {
    const result = await client.query('SELECT * FROM todos;');

    client.end();

    return success({
      message: `${result.rowCount} item(s) returned`,
      data: result.rows,
      status: true,
    });
  } catch (e) {
    console.error(e.stack);

    client.end();

    return failure({ message: e, status: false });
  }
}

vi.mock('pg', () => {
  const Client = vi.fn();
  Client.prototype.connect = vi.fn();
  Client.prototype.query = vi.fn();
  Client.prototype.end = vi.fn();

  return { Client };
});

vi.mock('./handlers.js', () => {
  return {
    success: vi.fn(),
    failure: vi.fn(),
  };
});

describe('bir todo öğesi listesi alma', () => {
  let client;

  beforeEach(() => {
    client = new Client();
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it('öğeleri başarıyla döndürmeli', async () => {
    client.query.mockResolvedValueOnce({ rows: [], rowCount: 0 });

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);

    expect(success).toBeCalledWith({
      message: '0 item(s) returned',
      data: [],
      status: true,
    });
  });

  it('bir hata fırlatmalı', async () => {
    const mError = new Error('Unable to retrieve rows');
    client.query.mockRejectedValueOnce(mError);

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);
    expect(failure).toBeCalledWith({ message: mError, status: false });
  });
});

İstekler ​

Vitest Node'da çalıştığı için, ağ isteklerini taklit etmek zordur; web API'leri kullanılamaz, bu nedenle ağ davranışını simüle edecek bir mekanizmaya ihtiyacımız var. Bunu başarmak için Mock Service Worker öneriyoruz. Hem REST hem de GraphQL ağ isteklerini sahtelemenize olanak tanır ve çerçeveden bağımsızdır.

Mock Service Worker (MSW), testlerinizin yaptığı istekleri engelleyerek çalışır ve herhangi bir uygulama kodunuzu değiştirmeden kullanmanıza olanak tanır. Tarayıcıda bu, Service Worker API kullanır. Node.js'de ve Vitest için @mswjs/interceptors kullanır. MSW hakkında daha fazla bilgi edinmek için giriş belgesini okuyun.

Yapılandırma ​

Yapılandırma dosyanızda aşağıdaki gibi kullanabilirsiniz:

js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { HttpResponse, graphql, http } from 'msw';

const posts = [
  {
    userId: 1,
    id: 1,
    title: 'first post title',
    body: 'first post body',
  },
  // ...
];

export const restHandlers = [
  http.get('https://rest-endpoint.example/path/to/posts', () => {
    return HttpResponse.json(posts);
  }),
];

const graphqlHandlers = [
  graphql.query('ListPosts', () => {
    return HttpResponse.json({
      data: { posts },
    });
  }),
];

const server = setupServer(...restHandlers, ...graphqlHandlers);

// Tüm testlerden önce sunucuyu başlat
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Tüm testlerden sonra sunucuyu kapat
afterAll(() => server.close());

// Her testten sonra işleyicileri sıfırla (`test izolasyonu için önemli`)
afterEach(() => server.resetHandlers());

Sunucuyu onUnhandleRequest: 'error' ile yapılandırmak, eşleşen bir istek işleyicisi olmayan bir istek olduğunda bir hata fırlatılmasını sağlar.

Örnek ​

MSW kullanan tam çalışan bir örneğimiz var: MSW ile React Testi.

Daha Fazla ​

MSW'de çok daha fazlası var. Çerezlere ve sorgu parametrelerine erişebilir, sahte hata yanıtları tanımlayabilir ve çok daha fazlasını yapabilirsiniz! MSW ile yapabileceğiniz her şeyi görmek için belgelerini okuyun.

Zamanlayıcılar ​

Zaman aşımlarını veya aralıkları içeren kodu test ettiğimizde, testlerimizin beklemesini veya zaman aşımına uğramasını sağlamak yerine, setTimeout ve setInterval çağrılarını sahteleyen "sahte" zamanlayıcılar kullanarak testlerimizi hızlandırabiliriz.

Daha ayrıntılı bir API açıklaması için vi.useFakeTimers api bölümüne bakın.

Örnek ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

function executeAfterTwoHours(func) {
  setTimeout(func, 1000 * 60 * 60 * 2); // 2 saat
}

function executeEveryMinute(func) {
  setInterval(func, 1000 * 60); // 1 dakika
}

const mock = vi.fn(() => console.log('executed'));

describe('gecikmeli yürütme', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });
  it('fonksiyonu yürütmeli', () => {
    executeAfterTwoHours(mock);
    vi.runAllTimers();
    expect(mock).toHaveBeenCalledTimes(1);
  });
  it('fonksiyonu yürütmemeli', () => {
    executeAfterTwoHours(mock);
    // 2ms ilerletmek işlevi tetiklemeyecektir
    vi.advanceTimersByTime(2);
    expect(mock).not.toHaveBeenCalled();
  });
  it('her dakika yürütmeli', () => {
    executeEveryMinute(mock);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(1);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(2);
  });
});

Hızlı Başvuru ​

INFO

Aşağıdaki örneklerdeki vi doğrudan vitestten içe aktarılır. Yapılandırmanızda globals'ı true olarak ayarlarsanız, global olarak da kullanabilirsiniz.

Şunları yapmak istiyorum:

Bir method üzerinde izleme yapmak ​

ts
const instance = new SomeClass();
vi.spyOn(instance, 'method');

Dışa aktarılmış değişkenleri mocklamak ​

js
// some-path.js
export const getter = 'variable';
ts
// some-path.test.ts
import * as exports from './some-path.js';

vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');

Dışa aktarılmış fonksiyonu mocklamak ​

  1. vi.mock ile örnek:

WARNING

Bir vi.mock çağrısının dosyanın en üstüne taşındığını unutmayın. Her zaman tüm içe aktarmalardan önce yürütülecektir.

ts
// ./some-path.js
export function method() {}
ts
import { method } from './some-path.js';

vi.mock('./some-path.js', () => ({
  method: vi.fn(),
}));
  1. vi.spyOn ile örnek:
ts
import * as exports from './some-path.js';

vi.spyOn(exports, 'method').mockImplementation(() => {});

Dışa aktarılmış sınıf uygulamasını mocklamak ​

  1. vi.mock ve .prototype ile örnek:
ts
// some-path.ts
export class SomeClass {}
ts
import { SomeClass } from './some-path.js';

vi.mock('./some-path.js', () => {
  const SomeClass = vi.fn();
  SomeClass.prototype.someMethod = vi.fn();
  return { SomeClass };
});
// SomeClass.mock.instances SomeClass örneklerini içerecektir
  1. vi.mock ve dönüş değeri ile örnek:
ts
import { SomeClass } from './some-path.js';

vi.mock('./some-path.js', () => {
  const SomeClass = vi.fn(() => ({
    someMethod: vi.fn(),
  }));
  return { SomeClass };
});
// SomeClass.mock.returns döndürülen nesneyi içerecektir
  1. vi.spyOn ile örnek:
ts
import * as exports from './some-path.js';

vi.spyOn(exports, 'SomeClass').mockImplementation(() => {
  // ilk iki örnekteki uygun olan uygulamayı seçebilirsiniz
});

Bir fonksiyondan döndürülen bir nesneyi izlemek ​

  1. Önbellek kullanarak örnek:
ts
// some-path.ts
export function useObject() {
  return { method: () => true };
}
ts
// useObject.js
import { useObject } from './some-path.js';

const obj = useObject();
obj.method();
ts
// useObject.test.js
import { useObject } from './some-path.js';

vi.mock('./some-path.js', () => {
  let _cache;
  const useObject = () => {
    if (!_cache) {
      _cache = {
        method: vi.fn(),
      };
    }
    // şimdi useObject() her çağrıldığında
    // aynı nesne referansını döndürecektir
    return _cache;
  };
  return { useObject };
});

const obj = useObject();
// obj.method some-path.js içinde çağrıldı
expect(obj.method).toHaveBeenCalled();

Bir modülün bir bölümünü mocklamak ​

ts
import { mocked, original } from './some-path.js';

vi.mock('./some-path.js', async importOriginal => {
  const mod = await importOriginal<typeof import('./some-path.js')>();
  return {
    ...mod,
    mocked: vi.fn(),
  };
});
original(); // orijinal davranışa sahip
mocked(); // bir izleme fonksiyonu

Geçerli tarihi mocklamak ​

Date'in zamanını mocklamak için vi.setSystemTime yardımcı fonksiyonunu kullanabilirsiniz. Bu değer, farklı testler arasında otomatik olarak sıfırlanmayacaktır.

vi.useFakeTimers kullanmanın Date'in zamanını da değiştirdiğine dikkat edin.

ts
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// taklit edilen zamanı sıfırlamak için
vi.useRealTimers();

Global değişkeni mocklamak ​

globalThis'e bir değer atayarak veya vi.stubGlobal yardımcısını kullanarak global değişken ayarlayabilirsiniz. vi.stubGlobal kullanırken, unstubGlobals yapılandırma seçeneğini etkinleştirmediğiniz veya vi.unstubAllGlobals çağırmadığınız sürece, bu değer farklı testler arasında otomatik olarak sıfırlanmayacaktır.

ts
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');

import.meta.env'yi mocklamak ​

  1. Bir ortam değişkenini değiştirmek için, ona yeni bir değer atamanız yeterlidir.

WARNING

Ortam değişkeninin değeri farklı testler arasında otomatik olarak sıfırlanmayacaktır sıfırlanmayacaktır .

ts
import { beforeEach, expect, it } from 'vitest';

// beforeEach kancasında manuel olarak sıfırlayabilirsiniz
const originalViteEnv = import.meta.env.VITE_ENV;

beforeEach(() => {
  import.meta.env.VITE_ENV = originalViteEnv;
});

it('değeri değiştirir', () => {
  import.meta.env.VITE_ENV = 'staging';
  expect(import.meta.env.VITE_ENV).toBe('staging');
});
  1. Değerleri otomatik olarak sıfırlamak isterseniz, unstubEnvs yapılandırma seçeneği etkinleştirilmiş halde vi.stubEnv yardımcısını kullanabilir (veya bir beforeEach kancasında vi.unstubAllEnvs](/api/vi#vi-unstuballenvs) öğesini manuel olarak çağırabilirsiniz):
ts
import { expect, it, vi } from 'vitest';

// testlerin çalıştırılmasından önce "VITE_ENV" "test"tir
import.meta.env.VITE_ENV === 'test';

it('değeri değiştirir', () => {
  vi.stubEnv('VITE_ENV', 'staging');
  expect(import.meta.env.VITE_ENV).toBe('staging');
});

it('değer, başka bir test çalıştırılmadan önce eski haline döner', () => {
  expect(import.meta.env.VITE_ENV).toBe('test');
});
ts
// vitest.config.ts
export default {
  test: {
    unstubAllEnvs: true,
  },
};
Pager
Önceki sayfaAnlık Görüntü (Snapshot) Testleri
Sonraki sayfaTürleri Test Etme

MIT Lisansı altında yayınlanmıştır.

Copyright (c) 2024 Mithril Contributors

https://v1.vitest.dev/guide/mocking

MIT Lisansı altında yayınlanmıştır.

Copyright (c) 2024 Mithril Contributors