Skip to content
Vitest 2
Main Navigation PrzewodnikAPIKonfiguracjaTryb przeglądarkiZaawansowany
2.1.9
1.6.1
0.34.6

Polski

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

Polski

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

Wygląd

Sidebar Navigation

Dlaczego Vitest

Wprowadzenie

Funkcje

Przestrzeń robocza

Interfejs Linii Poleceń

Filtrowanie Testów

Reportery

Pokrycie kodu

Snapshot

Mockowanie

Testowanie typów

Interfejs użytkownika Vitest

Testowanie w kodzie źródłowym

Kontekst Testowy

Środowisko Testowe

Rozszerzanie Matcherów

Integracje z IDE

Debugowanie

Porównania z innymi narzędziami do uruchamiania testów

Przewodnik migracji

Częste błędy

Profiling Test Performance

Poprawa wydajności

Na tej stronie

Mockowanie ​

Podczas pisania testów często zachodzi potrzeba stworzenia „fałszywej” wersji wewnętrznej lub zewnętrznej usługi. Jest to powszechnie nazywane mockowaniem. Vitest dostarcza funkcji pomocniczych, aby Ci w tym pomóc, poprzez swój pomocnik vi. Możesz zaimportować vi za pomocą import { vi } from 'vitest' lub uzyskać do niego dostęp globalnie (gdy konfiguracja globalna jest włączona).

WARNING

Zawsze pamiętaj, aby wyczyścić lub przywrócić mocki przed lub po każdym teście, aby cofnąć zmiany stanu między uruchomieniami! Więcej informacji znajdziesz w dokumentacji mockReset.

Jeśli chcesz od razu zagłębić się w temat, sprawdź sekcję API. W przeciwnym razie, czytaj dalej, aby głębiej zanurzyć się w świat mockowania.

Daty ​

Czasami musisz mieć kontrolę nad datą, aby zapewnić spójność testów. Vitest wykorzystuje pakiet @sinonjs/fake-timers do manipulowania timerami i datą systemową. Więcej o konkretnym API znajdziesz tutaj.

Przykład ​

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('purchasing flow', () => {
  beforeEach(() => {
    // informujemy Vitest, że używamy zamockowanego czasu
    vi.useFakeTimers();
  });

  afterEach(() => {
    // przywracamy datę po każdym teście
    vi.useRealTimers();
  });

  it('allows purchases within business hours', () => {
    // ustawiamy godzinę w godzinach pracy
    const date = new Date(2000, 1, 1, 13);
    vi.setSystemTime(date);

    // dostęp do Date.now() zwróci datę ustawioną powyżej
    expect(purchase()).toEqual({ message: 'Success' });
  });

  it('disallows purchases outside of business hours', () => {
    // ustawiamy godzinę poza godzinami pracy
    const date = new Date(2000, 1, 1, 19);
    vi.setSystemTime(date);

    // dostęp do Date.now() zwróci datę ustawioną powyżej
    expect(purchase()).toEqual({ message: 'Error' });
  });
});

Funkcje ​

Mockowanie funkcji dzieli się na dwie kategorie: szpiegowanie i mockowanie.

Czasami wystarczy sprawdzić, czy określona funkcja została wywołana (i ewentualnie jakie argumenty zostały przekazane). W takich przypadkach wystarczy szpieg, którego można użyć bezpośrednio z vi.spyOn() (czytaj więcej tutaj).

Jednak szpiedzy mogą jedynie szpiegować funkcje; nie są w stanie zmieniać ich implementacji. W przypadku, gdy musimy stworzyć fałszywą (lub zamockowaną) wersję funkcji, możemy użyć vi.fn() (czytaj więcej tutaj).

Używamy Tinyspy jako podstawy do mockowania funkcji, ale mamy własny wrapper, aby była kompatybilna z jest. Zarówno vi.fn(), jak i vi.spyOn() mają te same metody, jednak tylko wynik zwracany przez vi.fn() jest wywoływalny.

Przykład ​

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

const messages = {
  items: [
    { message: 'Simple test message', from: 'Testman' },
    // ...
  ],
  getLatest, // może być również `getterem lub setterem (jeśli obsługiwany)`
};

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

describe('reading messages', () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('should get the latest message with a spy', () => {
    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('should get with a mock', () => {
    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);
  });
});

Więcej ​

  • Funkcje mockujące Jest

Zmienne globalne ​

Możesz mockować zmienne globalne niedostępne w jsdom lub node, używając pomocnika vi.stubGlobal. Umieści to wartość zmiennej globalnej w obiekcie globalThis.

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);

// teraz możesz uzyskać do niego dostęp jako `IntersectionObserver` lub `window.IntersectionObserver`

Moduły ​

Mockowanie modułów pozwala na interakcję z bibliotekami stron trzecich, które są wywoływane w innym kodzie, umożliwiając testowanie argumentów, danych wyjściowych, a nawet ponowne deklarowanie ich implementacji.

Szczegółowy opis API znajdziesz w sekcji vi.mock() API.

Algorytm automatycznego mockowania ​

Jeśli Twój kod importuje zamockowany moduł, a dla tego modułu nie ma powiązanego pliku __mocks__ ani factory, Vitest zamockuje sam moduł, wywołując go i mockując każdy eksport.

Obowiązują następujące zasady:

  • Wszystkie tablice zostaną opróżnione
  • Wszystkie prymitywy i kolekcje pozostaną niezmienione
  • Wszystkie obiekty zostaną głęboko sklonowane
  • Wszystkie instancje klas i ich prototypy zostaną głęboko sklonowane

Moduły wirtualne ​

Vitest obsługuje mockowanie modułów wirtualnych Vite. Działa to inaczej niż w Jest. Zamiast przekazywać virtual: true do funkcji vi.mock, musisz poinformować Vite, że moduł istnieje, w przeciwnym razie wystąpi błąd podczas parsowania. Możesz to zrobić na kilka sposobów:

  1. Podaj alias
ts
// vitest.config.js
export default {
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
};
  1. Dostarcz wtyczkę, która rozwiązuje moduł wirtualny
ts
// vitest.config.js
export default {
  plugins: [
    {
      name: 'virtual-modules',
      resolveId(id) {
        if (id === '$app/forms') {
          return 'virtual:$app/forms';
        }
      },
    },
  ],
};

Zaletą drugiego podejścia jest to, że możesz dynamicznie tworzyć różne wirtualne punkty dostępu. Jeśli przekierujesz kilka modułów wirtualnych do jednego pliku, wszystkie z nich zostaną objęte działaniem vi.mock, więc upewnij się, że używasz unikalnych identyfikatorów.

Pułapki mockowania ​

Należy pamiętać, że nie można mockować wywołań metod, które są wywoływane wewnątrz innych metod tego samego pliku. Na przykład, w tym kodzie:

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

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

Nie jest możliwe mockowanie metody foo z zewnątrz, ponieważ jest ona bezpośrednio odwoływana. W związku z tym ten kod nie wpłynie na wywołanie foo wewnątrz foobar (ale wpłynie na wywołanie foo w innych modułach):

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

// to wpłynie tylko na "foo" poza oryginalnym modułem
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
  return {
    ...(await importOriginal<typeof import('./foobar.js')>()),
    // to wpłynie tylko na "foo" poza oryginalnym modułem
    foo: () => 'mocked',
  };
});

Możesz potwierdzić to zachowanie, dostarczając implementację metody foobar bezpośrednio:

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

vi.spyOn(mod, 'foo');

// wyeksportowane foo odwołuje się do zamockowanej funkcji
mod.foobar(mod.foo);
ts
// foobar.js
export function foo() {
  return 'foo';
}

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

Takie jest zamierzone zachowanie. Zazwyczaj jest to oznaka złego kodu, gdy mockowanie jest używane w ten sposób. Rozważ refaktoryzację kodu na wiele plików lub ulepszenie architektury aplikacji poprzez zastosowanie technik takich jak wstrzykiwanie zależności.

Przykład ​

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

// pobierz listę zadań
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('get a list of todo items', () => {
  let client;

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

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

  it('should return items successfully', 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('should throw an error', 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 });
  });
});

System plików ​

Mockowanie systemu plików zapewnia, że testy nie zależą od rzeczywistego systemu plików, czyniąc je bardziej niezawodnymi i przewidywalnymi. Ta izolacja zapobiega efektom ubocznym między testami. Pozwala na testowanie warunków błędów i przypadków brzegowych, które mogą być trudne lub niemożliwe do odtworzenia w rzeczywistym systemie plików (np. problemy z uprawnieniami, scenariusze pełnego dysku lub błędy odczytu/zapisu).

Vitest nie dostarcza żadnego API do mockowania systemu plików domyślnie. Możesz użyć vi.mock do ręcznego mockowania modułu fs, ale jest to trudne w utrzymaniu. Zamiast tego zalecamy użycie memfs, aby to za Ciebie zrobić. memfs tworzy system plików w pamięci, który symuluje operacje na systemie plików bez dotykania rzeczywistego dysku. To podejście jest szybkie i bezpieczne, pozwalając uniknąć wszelkich potencjalnych efektów ubocznych na rzeczywistym systemie plików.

Przykład ​

Aby automatycznie przekierować każde wywołanie fs do memfs, możesz utworzyć pliki __mocks__/fs.cjs i __mocks__/fs/promises.cjs w katalogu głównym swojego projektu:

ts
// możemy również użyć `import`, ale wtedy
// każdy eksport powinien być jawnie zdefiniowany

const { fs } = require('memfs');
module.exports = fs;
ts
// możemy również użyć `import`, ale wtedy
// każdy eksport powinien być jawnie zdefiniowany

const { fs } = require('memfs');
module.exports = fs.promises;
ts
// read-hello-world.js
import { readFileSync } from 'node:fs';

export function readHelloWorld(path) {
  return readFileSync(path);
}
ts
// hello-world.test.js
import { beforeEach, expect, it, vi } from 'vitest';
import { fs, vol } from 'memfs';
import { readHelloWorld } from './read-hello-world.js';

// poinformuj vitest, aby używał mocku fs z folderu __mocks__
// można to zrobić w pliku setup, jeśli fs zawsze powinien być mockowany
vi.mock('node:fs');
vi.mock('node:fs/promises');

beforeEach(() => {
  // resetuj stan systemu plików w pamięci
  vol.reset();
});

it('should return correct text', () => {
  const path = '/hello-world.txt';
  fs.writeFileSync(path, 'hello world');

  const text = readHelloWorld(path);
  expect(text).toBe('hello world');
});

it('can return a value multiple times', () => {
  // możesz użyć vol.fromJSON, aby zdefiniować kilka plików
  vol.fromJSON(
    {
      './dir1/hw.txt': 'hello dir1',
      './dir2/hw.txt': 'hello dir2',
    },
    // domyślny cwd
    '/tmp'
  );

  expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1');
  expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2');
});

Żądania ​

Ponieważ Vitest działa w Node.js, mockowanie żądań sieciowych stanowi wyzwanie; API webowe nie są dostępne, więc potrzebujemy czegoś, co będzie symulować zachowanie sieciowe. Zalecamy użycie Mock Service Worker, aby to osiągnąć. Pozwoli to na mockowanie zarówno żądań sieciowych REST, jak i GraphQL, oraz jest niezależne od frameworka.

Mock Service Worker (MSW) działa poprzez przechwytywanie żądań wysyłanych przez Twoje testy, co pozwala na jego użycie bez zmiany kodu aplikacji. W przeglądarce używa Service Worker API. W Node.js i dla Vitest, używa biblioteki @mswjs/interceptors. Aby dowiedzieć się więcej o MSW, przeczytaj ich wprowadzenie

Konfiguracja ​

Możesz użyć go w swoim pliku setup w następujący sposób:

js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { graphql, http, HttpResponse } 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);

// Uruchom serwer przed wszystkimi testami
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Zamknij serwer po wszystkich testach
afterAll(() => server.close());

// Zresetuj handlery po każdym teście `ważne dla izolacji testów`
afterEach(() => server.resetHandlers());

Konfiguracja serwera z onUnhandleRequest: 'error' zapewnia, że błąd zostanie zgłoszony, gdy pojawi się żądanie, które nie ma odpowiadającej mu obsługi żądań.

Więcej ​

MSW ma znacznie więcej do zaoferowania. Możesz uzyskać dostęp do ciasteczek i parametrów zapytania, definiować mockowe odpowiedzi błędów i wiele więcej! Aby zobaczyć wszystko, co możesz zrobić z MSW, przeczytaj ich dokumentację.

Timery ​

Kiedy testujemy kod, który zawiera timeouty lub interwały, zamiast czekać na ich zakończenie lub przekroczenie limitu czasu, możemy przyspieszyć nasze testy, używając „fałszywych” timerów, które mockują wywołania setTimeout i setInterval.

Szczegółowy opis API znajdziesz w sekcji vi.useFakeTimers API.

Przykład ​

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

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

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

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

describe('delayed execution', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });
  it('should execute the function', () => {
    executeAfterTwoHours(mock);
    vi.runAllTimers();
    expect(mock).toHaveBeenCalledTimes(1);
  });
  it('should not execute the function', () => {
    executeAfterTwoHours(mock);
    // przesunięcie o 2ms nie wywoła funkcji
    vi.advanceTimersByTime(2);
    expect(mock).not.toHaveBeenCalled();
  });
  it('should execute every minute', () => {
    executeEveryMinute(mock);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(1);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(2);
  });
});

Klasy ​

Całą klasę można zamockować jednym wywołaniem vi.fn – ponieważ wszystkie klasy są również funkcjami, działa to od razu. Należy pamiętać, że obecnie Vitest nie obsługuje słowa kluczowego new, więc new.target jest zawsze undefined w ciele funkcji.

ts
class Dog {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  static getType(): string {
    return 'animal';
  }

  speak(): string {
    return 'bark!';
  }

  isHungry() {}
  feed() {}
}

Możemy odtworzyć tę klasę za pomocą funkcji ES5:

ts
const Dog = vi.fn(function (name) {
  this.name = name;
});

// zauważ, że metody statyczne są mockowane bezpośrednio na obiekcie funkcji,
// a nie na instancji klasy
Dog.getType = vi.fn(() => 'mocked animal');

// mockuj metody "speak" i "feed" na każdej instancji klasy
// wszystkie instancje `new Dog()` będą miały te szpiegi
Dog.prototype.speak = vi.fn(() => 'loud bark!');
Dog.prototype.feed = vi.fn();

KIEDY UŻYWAĆ?

Ogólnie rzecz biorąc, zdefiniowałbyś klasę w ten sposób wewnątrz fabryki modułów, jeśli klasa jest ponownie eksportowana z innego modułu:

ts
import { Dog } from './dog.js';

vi.mock(import('./dog.js'), () => {
  const Dog = vi.fn();
  Dog.prototype.feed = vi.fn();
  // ... inne mocki
  return { Dog };
});

Ta metoda może być również użyta do przekazania instancji klasy do funkcji, która przyjmuje ten sam interfejs:

ts
// ./src/feed.ts
function feed(dog: Dog) {
  // ...
}

// ./tests/dog.test.ts
import { expect, test, vi } from 'vitest';
import { feed } from '../src/feed.js';

const Dog = vi.fn();
Dog.prototype.feed = vi.fn();

test('can feed dogs', () => {
  const dogMax = new Dog('Max');

  feed(dogMax);

  expect(dogMax.feed).toHaveBeenCalled();
  expect(dogMax.isHungry()).toBe(false);
});

Teraz, gdy tworzymy nową instancję klasy Dog, jej metoda speak (oraz feed) jest już zamockowana:

ts
const dog = new Dog('Cooper');
dog.speak(); // głośne szczekanie!

// możesz użyć wbudowanych asercji, aby sprawdzić poprawność wywołania
expect(dog.speak).toHaveBeenCalled();

Możemy ponownie przypisać wartość zwracaną dla konkretnej instancji:

ts
const dog = new Dog('Cooper');

// "vi.mocked" to pomocnik typów, ponieważ
// TypeScript nie wie, że Dog to zamockowana klasa,
// opakowuje każdą funkcję w typ MockInstance<T>
// nie sprawdzając, czy funkcja jest mockiem
vi.mocked(dog.speak).mockReturnValue('hau hau');

dog.speak(); // hau hau

Aby zamockować właściwość, możemy użyć metody vi.spyOn(dog, 'name', 'get'). Umożliwia to użycie asercji dla szpiega na zamockowanej właściwości:

ts
const dog = new Dog('Cooper');

const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max');

expect(dog.name).toBe('Max');
expect(nameSpy).toHaveBeenCalledTimes(1);

TIP

Możesz również szpiegować gettery i settery, korzystając z tej samej metody.

Ściągawka ​

INFO

vi w poniższych przykładach importuje się bezpośrednio z vitest. Możesz również używać go globalnie, jeśli ustawisz globals na true w swojej konfiguracji.

Potrzebuję…

Mockować eksportowane zmienne ​

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');

Mockować eksportowaną funkcję ​

  1. Przykład z vi.mock:

WARNING

Nie zapominaj, że wywołanie vi.mock jest podnoszone na początek pliku. Zawsze zostanie wykonane przed wszystkimi importami.

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

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

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

Mockować implementację eksportowanej klasy ​

  1. Przykład z vi.mock i .prototype:
ts
// ./some-path.ts
export class SomeClass {}
ts
import { SomeClass } from './some-path.js';

vi.mock(import('./some-path.js'), () => {
  const SomeClass = vi.fn();
  SomeClass.prototype.someMethod = vi.fn();
  return { SomeClass };
});
// SomeClass.mock.instances będzie zawierać instancje SomeClass
  1. Przykład z vi.spyOn:
ts
import * as mod from './some-path.js';

const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();

vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass);

Szpiegować obiekt zwrócony z funkcji ​

  1. Przykład użycia cache:
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(import('./some-path.js'), () => {
  let _cache;
  const useObject = () => {
    if (!_cache) {
      _cache = {
        method: vi.fn(),
      };
    }
    // teraz za każdym razem, gdy wywoływane jest useObject(),
    // zwróci to samo odwołanie do obiektu
    return _cache;
  };
  return { useObject };
});

const obj = useObject();
// obj.method zostało wywołane w module some-path
expect(obj.method).toHaveBeenCalled();

Mockować część modułu ​

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

vi.mock(import('./some-path.js'), async importOriginal => {
  const mod = await importOriginal();
  return {
    ...mod,
    mocked: vi.fn(),
  };
});
original(); // ma oryginalne zachowanie
mocked(); // jest funkcją szpiegującą

WARNING

Nie zapominaj, że to mockuje jedynie dostęp zewnętrzny. W tym przykładzie, jeśli original wywołuje mocked wewnętrznie, zawsze wywoła funkcję zdefiniowaną w module, a nie w fabryce mocków.

Mockować bieżącą datę ​

Aby zamockować czas Date, możesz użyć funkcji pomocniczej vi.setSystemTime. Ta wartość nie zostanie automatycznie zresetowana między kolejnymi testami.

Pamiętaj, że użycie vi.useFakeTimers również zmienia czas Date.

ts
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// zresetuj zamockowany czas
vi.useRealTimers();

Mockować zmienną globalną ​

Możesz ustawić zmienną globalną, przypisując wartość do globalThis lub używając pomocnika vi.stubGlobal. Podczas używania vi.stubGlobal, wartość nie zostanie automatycznie zresetowana między kolejnymi testami, chyba że włączysz opcję konfiguracyjną unstubGlobals lub wywołasz vi.unstubAllGlobals.

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

Mockować import.meta.env ​

  1. Aby zmienić zmienną środowiskową, możesz po prostu przypisać jej nową wartość.

WARNING

Wartość zmiennej środowiskowej nie zostanie automatycznie zresetowana między kolejnymi testami.

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

// przed uruchomieniem testów "VITE_ENV" ma wartość "test"
const originalViteEnv = import.meta.env.VITE_ENV;

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

it('changes value', () => {
  import.meta.env.VITE_ENV = 'staging';
  expect(import.meta.env.VITE_ENV).toBe('staging');
});
  1. Jeśli chcesz automatycznie zresetować wartość(i), możesz użyć pomocnika vi.stubEnv z włączoną opcją konfiguracyjną unstubEnvs (lub ręcznie wywołać vi.unstubAllEnvs w hooku beforeEach):
ts
import { expect, it, vi } from 'vitest';

// przed uruchomieniem testów "VITE_ENV" ma wartość "test"
import.meta.env.VITE_ENV === 'test';

it('changes value', () => {
  vi.stubEnv('VITE_ENV', 'staging');
  expect(import.meta.env.VITE_ENV).toBe('staging');
});

it('the value is restored before running an other test', () => {
  expect(import.meta.env.VITE_ENV).toBe('test');
});
ts
// vitest.config.ts
export default defineConfig({
  test: {
    unstubEnvs: true,
  },
});
Pager
Poprzednia stronaSnapshot
Następna stronaTestowanie typów

Opublikowano na licencji MIT.

Copyright (c) 2024 Mithril Contributors

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

Opublikowano na licencji MIT.

Copyright (c) 2024 Mithril Contributors