Skip to content
Vitest 0
Main Navigation ÚtmutatóAPIKonfigurációHaladó
1.6.1
0.34.6

magyar

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

magyar

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

Megjelenés

Sidebar Navigation

Útmutató

Miért a Vitest?

Első lépések

Funkciók

Munkaterület

Parancssori felület

Tesztszűrés

Lefedettség

Pillanatképek

Mockolás

Típusok tesztelése

Vitest UI

Böngésző mód (kísérleti)

Forráskódba épített tesztelés

Tesztkörnyezet

Tesztkörnyezet

Egyezésvizsgálók kiterjesztése

IDE integrációk

Hibakeresés

Összehasonlítás más tesztfuttatókkal

Migrálási útmutató

Gyakori hibák

API

Teszt API Dokumentáció

Mock függvények

Vi

expect

expectTypeOf

assertType

Konfiguráció

Vitest konfigurálása

Ezen az oldalon

Mockolás ​

Tesztek írásakor előbb-utóbb szükségessé válik belső vagy külső szolgáltatások "hamis" verziójának létrehozása. Ezt általában mockolásnak nevezzük. A Vitest segédfüggvényeket biztosít a vi segítővel. Importálhatod a import { vi } from 'vitest' használatával, vagy globálisan is elérheted (ha a globális konfiguráció engedélyezve van).

WARNING

A mockok állapotváltozásainak elkerülése érdekében ne felejtsd el törölni vagy visszaállítani a mockokat minden tesztfuttatás előtt vagy után! További információért lásd a mockReset dokumentációt.

Ha azonnal belevágnál, nézd meg az [API szekciót]; ha nem, olvass tovább, hogy mélyebben belemerülj a mockolás világába.

Dátumok ​

Néha szükség lehet a dátum kontrollálására, hogy biztosítsd a konzisztenciát a tesztelés során. A Vitest a @sinonjs/fake-timers csomagot használja az időzítők, valamint a rendszerdátum manipulálására. Az API-ról részletesebben itt találsz információt.

Példa ​

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(() => {
    // tell vitest we use mocked time
    vi.useFakeTimers();
  });

  afterEach(() => {
    // restoring date after each test run
    vi.useRealTimers();
  });

  it('allows purchases within business hours', () => {
    // set hour within business hours
    const date = new Date(2000, 1, 1, 13);
    vi.setSystemTime(date);

    // access Date.now() will result in the date set above
    expect(purchase()).toEqual({ message: 'Success' });
  });

  it('disallows purchases outside of business hours', () => {
    // set hour outside business hours
    const date = new Date(2000, 1, 1, 19);
    vi.setSystemTime(date);

    // access Date.now() will result in the date set above
    expect(purchase()).toEqual({ message: 'Error' });
  });
});

Függvények ​

A függvények mockolása két különböző kategóriába sorolható: kémkedés (spying) és mockolás.

Néha csak azt kell ellenőrizned, hogy egy adott függvény meghívásra került-e (és esetleg milyen argumentumokkal). Ezekben az esetekben egy kém (spy) lenne minden, amire szükséged van, amelyet közvetlenül a vi.spyOn() segítségével használhatsz (további információ itt).

A spy-ok azonban csak a függvények megfigyelésében segíthetnek, nem képesek megváltoztatni ezen függvények implementációját. Abban az esetben, ha egy függvény hamis (vagy mockolt) verzióját kell létrehoznunk, használhatjuk a vi.fn()-t (további információ itt).

A Tinyspy-t használjuk a függvények mockolásának alapjaként, de van saját csomagunk, hogy jest kompatibilis legyen. Mind a vi.fn(), mind a vi.spyOn() ugyanazokat a metódusokat osztja meg, azonban csak a vi.fn() visszatérési értéke hívható.

Példa ​

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, // can also be a `getter or setter if supported`
};

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

További információk ​

  • Jest Mock Functions

Globális változók ​

A vi.stubGlobal segítővel mockolhatod azokat a globális változókat, amelyek nincsenek jelen a jsdom-ban vagy a node-ban. Ez a globális változó értékét a globalThis objektumba helyezi.

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

// now you can access it as `IntersectionObserver` or `window.IntersectionObserver`

Modulok ​

A modulok mockolása lehetővé teszi a harmadik féltől származó könyvtárak használatának megfigyelését, az argumentumok és a kimenet tesztelését, vagy akár az implementáció újradefiniálását.

A részletes API leírásért lásd a vi.mock() API szekciót.

Automockoló algoritmus ​

Ha a kódod egy mockolt modult importál anélkül, hogy tartozna hozzá __mocks__ fájl vagy factory, a Vitest magát a modult fogja mockolni a meghívásával és az összes export mockolásával.

A következő elvek érvényesek:

  • Minden tömb kiürül
  • Minden primitív és gyűjtemény változatlan marad
  • Minden objektum mélyen klónozva lesz
  • Az osztályok és prototípusaik minden példánya mélyen klónozva lesz

Példa ​

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

// handlers
export function success(data) {}
export function failure(data) {}

// get todos
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('teendőlista lekérése', () => {
  let client;

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

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

  it('sikeresen vissza kell adnia az elemeket.', 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('hibát kell dobnia.', 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 });
  });
});

Kérések ​

Mivel a Vitest Node-ban fut, a hálózati kérések mockolása nehézkes; a webes API-k nem érhetők el, ezért szükségünk van valamire, ami utánozza a hálózati viselkedést. Ehhez a Mock Service Worker használatát javasoljuk. Ez lehetővé teszi mind a REST, mind a GraphQL hálózati kérések mockolását, és keretrendszer-független.

A Mock Service Worker (MSW) úgy működik, hogy elfogja a tesztek által végrehajtott kéréseket, lehetővé téve a használatát anélkül, hogy meg kellene változtatnod az alkalmazáskódodat. Böngészőben ez a Service Worker API-t használja. A Node.js-ben és a Vitest esetében a node-request-interceptor-t használja. Ha többet szeretnél megtudni az MSW-ről, olvasd el a bevezetőjüket.

Konfiguráció ​

Az alábbiak szerint használhatod a setup fájlban:

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

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

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

const graphqlHandlers = [
  graphql.query(
    'https://graphql-endpoint.example/api/v1/posts',
    (req, res, ctx) => {
      return res(ctx.data(posts));
    }
  ),
];

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

// Start server before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

//  Close server after all tests
afterAll(() => server.close());

// Reset handlers after each test `important for test isolation`
afterEach(() => server.resetHandlers());

A szerver onUnhandleRequest: 'error' beállítással történő konfigurálása biztosítja, hogy hiba keletkezzen, ha olyan kérés érkezik, amelyhez nincs definiálva kéréskezelő.

Példa ​

Van egy teljes működő példánk, amely MSW-t használ: React Testing with MSW.

További információk ​

Az MSW sokkal többet tud. Hozzáférhetsz a cookie-khoz és a lekérdezési paraméterekhez, definiálhatsz mock hiba válaszokat és még sok mást! Ha mindent meg szeretnél tudni, amit az MSW-vel tehetsz, olvasd el a dokumentációjukat.

Időzítők ​

Amikor időzítéseket vagy intervallumokat használó kódot tesztelünk, ahelyett, hogy a tesztek várakoznának vagy időtúllépést okoznának, felgyorsíthatjuk a tesztelést a setTimeout és a setInterval hívásokat mockoló "hamis" időzítőkkel.

A részletesebb API leíráshoz lásd a vi.useFakeTimers API szekciót.

Példa ​

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

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

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

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

describe('késleltetett végrehajtás.', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });
  it('végre kell hajtania a függvényt.', () => {
    executeAfterTwoHours(mock);
    vi.runAllTimers();
    expect(mock).toHaveBeenCalledTimes(1);
  });
  it('nem szabad végrehajtania a függvényt.', () => {
    executeAfterTwoHours(mock);
    // advancing by 2ms won't trigger the func
    vi.advanceTimersByTime(2);
    expect(mock).not.toHaveBeenCalled();
  });
  it('percenként végre kell hajtania.', () => {
    executeEveryMinute(mock);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(1);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(2);
  });
});

Segédlet ​

INFO

Az alábbi példákban a vi közvetlenül a vitest-ből van importálva. Használhatod globálisan is, ha a konfigurációban a globals értékét true-ra állítod.

A következőt szeretném…

  • A method metódus kémlelése
ts
const instance = new SomeClass();
vi.spyOn(instance, 'method');
  • Exportált változók mockolása
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');
  • Exportált függvény mockolása

Példa vi.mock használatával:

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

vi.mock('./some-path.js', () => ({
  method: vi.fn(),
}));

WARNING

Ne felejtsd el, hogy a vi.mock hívás a fájl elejére kerül (hoisting). Ne helyezz vi.mock hívásokat a beforeEach blokkba, mert csak az egyik fogja ténylegesen mock-olni a modult.

Példa vi.spyOn használatával:

ts
import * as exports from './some-path.js';

vi.spyOn(exports, 'method').mockImplementation(() => {});
  • Exportált osztály implementációjának mockolása

Példa vi.mock és prototípus használatával:

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 };
});
// A SomeClass.mock.instances tartalmazni fogja a SomeClass példányait

Példa vi.mock és visszatérési érték használatával:

ts
import { SomeClass } from './some-path.js';

vi.mock('./some-path.js', () => {
  const SomeClass = vi.fn(() => ({
    someMethod: vi.fn(),
  }));
  return { SomeClass };
});
// A SomeClass.mock.results tartalmazni fogja a visszaadott objektumokat

Példa vi.spyOn használatával:

ts
import * as exports from './some-path.js';

vi.spyOn(exports, 'SomeClass').mockImplementation(() => {
  // bármi, ami az első két példában szerepel
});
  • Egy függvény által visszaadott objektum kémlelése

Példa gyorsítótár (cache) használatával:

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(),
      };
    }
    // a useObject() minden hívásakor
    // ugyanazt az objektum referenciát adja vissza
    return _cache;
  };
  return { useObject };
});

const obj = useObject();
// az `obj.method` meghívásra került a `some-path` modulban
expect(obj.method).toHaveBeenCalled();
  • Egy modul egy részének mockolása
ts
import { mocked, original } from './some-path.js';

vi.mock('./some-path.js', async () => {
  const mod = await vi.importActual<typeof import('./some-path.js')>(
    './some-path.js'
  );
  return {
    ...mod,
    mocked: vi.fn(),
  };
});
original(); // eredeti viselkedés
mocked(); // egy kémlelő függvény
  • Az aktuális dátum mockolása

A Date időpontjának mockolásához használhatod a vi.setSystemTime segédfüggvényt. Ez az érték nem fog automatikusan visszaállni a különböző tesztek között.

Ne feledd, hogy a vi.useFakeTimers használata szintén megváltoztatja a Date időpontját.

ts
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// a mockolt idő visszaállítása
vi.useRealTimers();
  • Globális változó mockolása

Globális változót beállíthatsz érték hozzárendelésével a globalThis-hez, vagy a vi.stubGlobal segédfüggvény használatával. A vi.stubGlobal használatakor ez nem fog automatikusan visszaállni a különböző tesztek között, hacsak nem engedélyezed az unstubGlobals konfigurációs opciót, vagy nem hívod meg a vi.unstubAllGlobals függvényt.

ts
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');
  • Az import.meta.env mockolása

A környezeti változó megváltoztatásához egyszerűen hozzárendelhetsz egy új értéket. Ez az érték nem fog automatikusan visszaállni a különböző tesztek között.

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

// manuálisan visszaállíthatod a `beforeEach` hook-ban
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');
});

Ha azt szeretnéd, hogy az érték automatikusan visszaállításra kerüljön, használhatod a vi.stubEnv segédfüggvényt az engedélyezett unstubEnvs konfigurációs opcióval (vagy manuálisan meghívhatod a vi.unstubAllEnvs függvényt a beforeEach hook-ban):

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

// a tesztek futtatása előtt a `VITE_ENV` értéke `test`
import.meta.env.VITE_ENV === 'test';

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

it('az érték visszaállításra kerül egy másik teszt futtatása előtt', () => {
  expect(import.meta.env.VITE_ENV).toBe('test');
});
ts
// vitest.config.ts
export default {
  test: {
    unstubAllEnvs: true,
  },
};
Pager
Előző oldalPillanatképek
Következő oldalTípusok tesztelése

A MIT licenc alapján kiadva.

Copyright (c) 2024 Mithril Contributors

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

A MIT licenc alapján kiadva.

Copyright (c) 2024 Mithril Contributors