Skip to content
Vitest 1
Main Navigation 가이드API구성고급
1.6.1
0.34.6

한국어

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
magyar

외관

Sidebar Navigation

가이드

Vitest를 선택하는 이유

시작하기

기능

워크스페이스

명령줄 인터페이스

테스트 필터링

리포터

커버리지

스냅샷

모의화

타입 테스트

Vitest UI

브라우저 모드

소스 내 테스트

테스트 컨텍스트

테스트 환경

Matcher 확장하기

IDE 통합

디버깅

다른 테스트 러너와의 비교

마이그레이션 가이드

일반적인 오류

성능 향상

API

테스트 API 참조

Mock 함수

Vi

expect

expectTypeOf

assert

assertType

구성

Vitest 구성 파일 관리

Vitest 구성하기

이 페이지에서

Vi ​

Vitest는 vi 헬퍼를 통해 유틸리티 함수를 제공합니다. 전역적으로 접근하거나 (globals 설정이 활성화된 경우), vitest에서 직접 가져올 수 있습니다.

js
import { vi } from 'vitest';

모듈 모의(Mock) ​

이 섹션에서는 모듈 모의 시 사용할 수 있는 API를 설명합니다. Vitest는 require()를 사용하여 가져온 모듈의 모의를 지원하지 않으므로 주의하세요.

vi.mock ​

  • 타입: (path: string, factory?: (importOriginal: () => unknown) => unknown) => void

제공된 path에서 가져온 모듈을 다른 모듈로 대체합니다. 경로 내에서 구성된 Vite 별칭을 사용할 수 있습니다. vi.mock 호출은 호이스팅되므로 호출 위치는 중요하지 않습니다. 항상 모든 import 전에 실행됩니다. 스코프 밖의 변수를 참조해야 한다면, vi.hoisted 안에 변수를 정의하고 vi.mock 안에서 참조하세요.

WARNING

vi.mock은 import 구문으로 가져온 모듈에만 작동하며, require 구문에는 작동하지 않습니다.

vi.mock을 호이스팅하기 위해 Vitest는 파일을 정적 분석합니다. 이는 vitest 패키지에서 직접 import하지 않은 vi (예: 유틸리티 파일에서 가져온 경우)는 사용할 수 없다는 의미입니다. vitest에서 가져온 vi와 함께 vi.mock을 사용하거나 globals 구성 옵션을 활성화하십시오.

Vitest는 설정 파일 내에서 가져온 모듈은 테스트 파일 실행 시 캐시되므로 모의하지 않습니다. 테스트 파일을 실행하기 전에 모든 모듈 캐시를 지우려면 vi.hoisted 내부에서 vi.resetModules()를 호출할 수 있습니다.

WARNING

브라우저 모드는 현재 모듈 모의를 지원하지 않습니다. GitHub 이슈에서 이 기능을 추적할 수 있습니다.

factory가 정의되면 모든 import는 해당 결과를 반환합니다. Vitest는 factory를 한 번만 호출하고 vi.unmock 또는 vi.doUnmock이 호출될 때까지 이후의 모든 import에 대해 결과를 캐시합니다.

jest와 달리 factory는 비동기적일 수 있습니다. vi.importActual 또는 factory에 첫 번째 인수로 전달된 헬퍼를 사용하여 내부에서 원래 모듈을 가져올 수 있습니다.

js
import { vi } from 'vitest';
// ---cut---
// JavaScript를 사용하는 경우

vi.mock('./path/to/module.js', async importOriginal => {
  const mod = await importOriginal();
  return {
    ...mod,
    // 일부 exports 대체
    namedExport: vi.fn(),
  };
});
ts
// TypeScript를 사용하는 경우

vi.mock('./path/to/module.js', async importOriginal => {
  const mod = await importOriginal<typeof import('./path/to/module.js')>();
  return {
    ...mod,
    // 일부 exports 대체
    namedExport: vi.fn(),
  };
});

WARNING

vi.mock은 파일의 맨 위로 호이스팅됩니다. 즉, beforeEach 또는 test 내부에서 작성하든 실제로 그 전에 호출됩니다.

이는 또한 factory 외부에서 정의된 변수를 factory 내부에서 사용할 수 없음을 의미합니다.

factory 안에서 변수를 사용해야 한다면 vi.doMock을 사용해 보세요. 작동 방식은 동일하지만 호이스팅되지 않습니다. 이후 import만 모의한다는 점에 유의하십시오.

vi.mock 전에 선언된 경우 vi.hoisted 메서드로 정의된 변수를 참조할 수도 있습니다.

ts
import { namedExport } from './path/to/module.js';

const mocks = vi.hoisted(() => {
  return {
    namedExport: vi.fn(),
  };
});

vi.mock('./path/to/module.js', () => {
  return {
    namedExport: mocks.namedExport,
  };
});

vi.mocked(namedExport).mockReturnValue(100);

expect(namedExport()).toBe(100);
expect(namedExport).toBe(mocks.namedExport);

WARNING

default export를 사용하는 모듈을 모의 처리할 때는, 반환되는 factory 함수 객체 안에 default 키를 포함해야 합니다. 이는 ES 모듈 관련 주의 사항입니다. 따라서 jest는 CommonJS 모듈을 사용하므로 jest 설명서와 다를 수 있습니다. 예를 들어,

ts
vi.mock('./path/to/module.js', () => {
  return {
    default: { myDefaultKey: vi.fn() },
    namedExport: vi.fn(),
    // 기타...
  };
});

모의하려는 파일과 함께 __mocks__ 폴더가 있고 factory가 제공되지 않은 경우 Vitest는 __mocks__ 하위 폴더에서 동일한 이름의 파일을 찾아 실제 모듈로 사용하려고 시도합니다. 종속성을 모의하는 경우 Vitest는 프로젝트의 루트에서 __mocks__ 폴더를 찾으려고 시도합니다(기본값은 process.cwd()입니다). deps.moduleDirectories 구성 옵션을 통해 Vitest에 종속성이 있는 위치를 알릴 수 있습니다.

예를 들어 다음과 같은 파일 구조가 있습니다.

- __mocks__
  - axios.js
- src
  __mocks__
    - increment.js
  - increment.js
- tests
  - increment.test.js

factory가 제공되지 않은 테스트 파일에서 vi.mock을 호출하면 모듈로 사용할 __mocks__ 폴더에서 파일을 찾습니다.

ts
// increment.test.js
import { vi } from 'vitest';

// axios는 `__mocks__/axios.js`의 기본 내보내기입니다.
import axios from 'axios';

// increment는 `src/__mocks__/increment.js`의 명명된 내보내기입니다.
import { increment } from '../increment.js';

vi.mock('axios');
vi.mock('../increment.js');

axios.get(`/apples/${increment(1)}`);

WARNING

vi.mock을 호출해야 모듈이 모의 처리됩니다. Jest의 자동 모의 동작을 복제하려면 setupFiles 내에서 필요한 각 모듈에 대해 vi.mock을 호출할 수 있습니다.

__mocks__ 폴더가 없거나 factory가 제공되지 않은 경우 Vitest는 원래 모듈을 가져오고 모든 내보내기를 자동 모의합니다. 적용되는 규칙은 알고리즘을 참조하십시오.

vi.doMock ​

  • 타입: (path: string, factory?: (importOriginal: () => unknown) => unknown) => void

vi.mock과 동일하지만 파일 맨 위로 호이스팅되지 않으므로 전역 파일 스코프에서 변수를 참조할 수 있습니다. 모듈의 다음 동적 import가 모의됩니다.

WARNING

이 함수는 호출되기 전에 import된 모듈은 모의 처리하지 않습니다. ESM의 모든 정적 import는 항상 호이스팅되므로 정적 import 앞에 배치해도 import 전에 호출되도록 강제할 수 없습니다.

ts
vi.doMock('./increment.js'); // 이는 import 문 _다음에_ 호출됩니다.

import { increment } from './increment.js';
ts
// ./increment.js
export function increment(number) {
  return number + 1;
}
ts
import { beforeEach, test } from 'vitest';
import { increment } from './increment.js';

// vi.doMock이 아직 호출되지 않았으므로 모듈이 모의되지 않았습니다.
increment(1) === 2;

let mockedIncrement = 100;

beforeEach(() => {
  // factory 내부에서 변수에 접근할 수 있습니다.
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});

test('다음에 import되는 모듈은 mock 처리된 모듈입니다.', async () => {
  // 원래 import는 import _다음에_ vi.doMock이 평가되었으므로 모의되지 않았습니다.
  expect(increment(1)).toBe(2);
  const { increment: mockedIncrement } = await import('./increment.js');
  // 새로운 동적 import는 모의된 모듈을 반환합니다.
  expect(mockedIncrement(1)).toBe(101);
  expect(mockedIncrement(1)).toBe(102);
  expect(mockedIncrement(1)).toBe(103);
});

vi.mocked ​

  • 타입: <T>(obj: T, deep?: boolean) => MaybeMockedDeep<T>
  • 타입: <T>(obj: T, options?: { partial?: boolean; deep?: boolean }) => MaybePartiallyMockedDeep<T>

TypeScript용 타입 헬퍼입니다. 전달된 객체를 반환합니다.

partial이 true이면 Partial<T>를 반환 값으로 예상합니다. 기본적으로 TypeScript는 첫 번째 레벨의 값만 mock 처리되었다고 인식합니다. 실제로 전체 객체가 모의된 경우 두 번째 인수로 { deep: true }를 전달하여 TypeScript에 알릴 수 있습니다.

ts
import example from './example.js';

vi.mock('./example.js');

test('1 + 1은 10과 같습니다.', async () => {
  vi.mocked(example.calc).mockReturnValue(10);
  expect(example.calc(1, '+', 1)).toBe(10);
});

vi.importActual ​

  • 타입: <T>(path: string) => Promise<T>

모의 여부 검사를 모두 건너뛰고 모듈을 가져옵니다. 모듈을 부분적으로 모의하려는 경우에 유용합니다.

ts
vi.mock('./example.js', async () => {
  const axios = await vi.importActual('./example.js');

  return { ...axios, get: vi.fn() };
});

vi.importMock ​

  • 타입: <T>(path: string) => Promise<MaybeMockedDeep<T>>

모든 속성(중첩된 속성 포함)이 모의된 모듈을 가져옵니다. vi.mock과 동일한 규칙을 따릅니다. 적용되는 규칙은 알고리즘을 참조하십시오.

vi.unmock ​

  • 타입: (path: string) => void

모의된 레지스트리에서 모듈을 제거합니다. 이전에 모의되었더라도 모든 import 호출은 원본 모듈을 반환합니다. 이 호출은 파일 상단으로 호이스팅되므로, 예를 들어 setupFiles에 정의된 모듈만 unmock 처리할 수 있습니다.

vi.doUnmock ​

  • 타입: (path: string) => void

vi.unmock과 동일하지만 파일 맨 위로 호이스팅되지 않습니다. 모듈의 다음 import는 모의 대신 원래 모듈을 가져옵니다. 이는 이전에 가져온 모듈을 unmock하지 않습니다.

ts
// ./increment.js
export function increment(number) {
  return number + 1;
}
ts
import { increment } from './increment.js';

// vi.mock이 호이스팅되었으므로 increment는 이미 모의되었습니다.
increment(1) === 100;

// 이는 호이스팅되고 factory는 1행의 import 전에 호출됩니다.
vi.mock('./increment.js', () => ({ increment: () => 100 }));

// 모든 호출이 모의되고 `increment`는 항상 100을 반환합니다.
increment(1) === 100;
increment(30) === 100;

// 이는 호이스팅되지 않으므로 다른 import는 unmock된 모듈을 반환합니다.
vi.doUnmock('./increment.js');

// `vi.doUnmock`이 모듈을 재평가하지 않으므로 이는 여전히 100을 반환합니다.
increment(1) === 100;
increment(30) === 100;

// 다음 import는 unmock되었으며 이제 `increment`는 count + 1을 반환하는 원래 함수입니다.
const { increment: unmockedIncrement } = await import('./increment.js');

unmockedIncrement(1) === 2;
unmockedIncrement(30) === 31;

vi.resetModules ​

  • 타입: () => Vitest

모든 모듈의 캐시를 지워 모듈 레지스트리를 재설정합니다. 이를 통해 모듈을 다시 가져올 때 재평가할 수 있습니다. 최상위 import는 재평가할 수 없습니다. 테스트 간에 로컬 상태가 충돌하는 모듈을 분리하는 데 유용합니다.

ts
import { vi } from 'vitest';

import { data } from './data.js'; // 각 테스트 전에 재평가되지 않습니다.

beforeEach(() => {
  vi.resetModules();
});

test('상태 변경', async () => {
  const mod = await import('./some/path.js'); // 재평가됩니다.
  mod.changeLocalState('new value');
  expect(mod.getLocalState()).toBe('new value');
});

test('모듈에 이전 상태가 있습니다.', async () => {
  const mod = await import('./some/path.js'); // 재평가됩니다.
  expect(mod.getLocalState()).toBe('old value');
});

WARNING

모의 레지스트리를 재설정하지 않습니다. 모의 레지스트리를 지우려면 vi.unmock 또는 vi.doUnmock을 사용하십시오.

vi.dynamicImportSettled ​

모든 import가 로드될 때까지 기다립니다. 기다릴 수 없는 모듈을 import하는 동기 호출이 있을 때 유용합니다.

ts
import { expect, test } from 'vitest';

// Promise가 반환되지 않으므로 import를 추적할 수 없습니다.
function renderComponent() {
  import('./component.js').then(({ render }) => {
    render();
  });
}

test('작업이 완료되었습니다.', async () => {
  renderComponent();
  await vi.dynamicImportSettled();
  expect(document.querySelector('.component')).not.toBeNull();
});

TIP

동적 import 중에 다른 동적 import가 시작되면 이 메서드는 모두 해결될 때까지 기다립니다.

이 메서드는 import가 완료된 후 다음 setTimeout 주기를 기다리므로 모든 동기식 작업은 해결될 때까지 완료되어야 합니다.

함수 및 객체 모의 ​

이 섹션에서는 메서드 모의를 사용하는 방법과 환경 및 전역 변수를 대체하는 방법을 설명합니다.

vi.fn ​

  • 타입: (fn?: Function) => Mock

함수에 대한 스파이를 만들지만, 함수 없이도 만들 수 있습니다. 함수가 호출될 때마다 호출 인수, 반환 값 및 인스턴스를 저장합니다. 또한 메서드를 사용하여 동작을 조작할 수 있습니다. 함수가 제공되지 않으면 모의는 호출될 때 undefined를 반환합니다.

ts
import { expect, vi } from 'vitest';
// ---cut---
const getApples = vi.fn(() => 0);

getApples();

expect(getApples).toHaveBeenCalled();
expect(getApples).toHaveReturnedWith(0);

getApples.mockReturnValueOnce(5);

const res = getApples();
expect(res).toBe(5);
expect(getApples).toHaveNthReturnedWith(2, 5);

vi.isMockFunction ​

  • 타입: (fn: Function) => boolean

지정된 매개변수가 모의 함수인지 확인합니다. TypeScript를 사용하는 경우 해당 타입도 좁혀집니다.

vi.clearAllMocks ​

모든 감시 함수에서 .mockClear()를 호출합니다. 이것은 모의 기록을 지우지만 기본 구현으로 재설정하지는 않습니다.

vi.resetAllMocks ​

모든 감시 함수에서 .mockReset()를 호출합니다. 이것은 모의 기록을 지우고 구현을 빈 함수로 재설정합니다(undefined를 반환합니다).

vi.restoreAllMocks ​

모든 감시 함수에서 .mockRestore()를 호출합니다. 이것은 모의 기록을 지우고 구현을 원래 구현으로 재설정합니다.

vi.spyOn ​

  • 타입: <T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance

vi.fn()과 유사하게 객체의 메서드 또는 getter/setter에 대한 감시 함수를 생성합니다. 모의 함수를 반환합니다.

ts
import { expect, vi } from 'vitest';
// ---cut---
let apples = 0;
const cart = {
  getApples: () => 42,
};

const spy = vi.spyOn(cart, 'getApples').mockImplementation(() => apples);
apples = 1;

expect(cart.getApples()).toBe(1);

expect(spy).toHaveBeenCalled();
expect(spy).toHaveReturnedWith(1);

TIP

모든 메서드를 원래 상태로 되돌리려면 afterEach 안에서 vi.restoreAllMocks를 호출하거나, test.restoreMocks를 활성화하면 됩니다. 이것은 원래 객체 설명자를 복원하므로 메서드의 구현을 변경할 수 없습니다.

ts
const cart = {
  getApples: () => 42,
};

const spy = vi.spyOn(cart, 'getApples').mockReturnValue(10);

console.log(cart.getApples()); // 10
vi.restoreAllMocks();
console.log(cart.getApples()); // 42
spy.mockReturnValue(10);
console.log(cart.getApples()); // 여전히 42!

vi.stubEnv 0.26.0+ ​

  • 타입: (name: string, value: string) => Vitest

process.env와 import.meta.env의 환경 변수 값을 변경합니다. vi.unstubAllEnvs를 호출하여 값을 복원할 수 있습니다.

ts
import { vi } from 'vitest';

// "vi.stubEnv"를 호출하기 전에 `process.env.NODE_ENV` 및 `import.meta.env.NODE_ENV`는 "development"입니다.

vi.stubEnv('NODE_ENV', 'production');

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';
// 다른 env는 변경하지 않습니다.
import.meta.env.MODE === 'development';

TIP

값을 직접 할당하여 변경할 수도 있지만 vi.unstubAllEnvs를 사용하여 이전 값을 복원할 수는 없습니다.

ts
import.meta.env.MODE = 'test';

vi.unstubAllEnvs 0.26.0+ ​

  • 타입: () => Vitest

vi.stubEnv로 변경된 모든 import.meta.env 및 process.env 값을 복원합니다. 처음 호출될 때 Vitest는 원래 값을 기억해두고, unstubAllEnvs가 다시 호출될 때까지 보관합니다.

ts
import { vi } from 'vitest';

// stubEnv를 호출하기 전에 `process.env.NODE_ENV` 및 `import.meta.env.NODE_ENV`는 "development"입니다.

vi.stubEnv('NODE_ENV', 'production');

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';

vi.stubEnv('NODE_ENV', 'staging');

process.env.NODE_ENV === 'staging';
import.meta.env.NODE_ENV === 'staging';

vi.unstubAllEnvs();

// 첫 번째 "stubEnv" 호출 전에 저장된 값으로 복원합니다.
process.env.NODE_ENV === 'development';
import.meta.env.NODE_ENV === 'development';

vi.stubGlobal ​

  • 타입: (name: string | number | symbol, value: unknown) => Vitest

전역 변수 값을 변경합니다. vi.unstubAllGlobals를 호출하여 원래 값을 복원할 수 있습니다.

ts
import { vi } from 'vitest';

// stubGlobal을 호출하기 전에 `innerWidth`는 "0"입니다.

vi.stubGlobal('innerWidth', 100);

innerWidth === 100;
globalThis.innerWidth === 100;
// jsdom 또는 happy-dom을 사용하는 경우
window.innerWidth === 100;

TIP

globalThis 또는 window( jsdom 또는 happy-dom 환경을 사용하는 경우)에 직접 할당하여 값을 변경할 수도 있지만 vi.unstubAllGlobals를 사용하여 원래 값을 복원할 수는 없습니다.

ts
globalThis.innerWidth = 100;
// jsdom 또는 happy-dom을 사용하는 경우
window.innerWidth = 100;

vi.unstubAllGlobals 0.26.0+ ​

  • 타입: () => Vitest

vi.stubGlobal로 변경된 globalThis/global(및 window/top/self/parent, jsdom 또는 happy-dom 환경을 사용하는 경우)의 모든 전역 값을 복원합니다. 처음 호출될 때 Vitest는 원래 값을 기억해두고, unstubAllGlobals가 다시 호출될 때까지 보관합니다.

ts
import { vi } from 'vitest';

const Mock = vi.fn();

// "stubGlobal"을 호출하기 전에 IntersectionObserver는 "undefined"입니다.

vi.stubGlobal('IntersectionObserver', Mock);

IntersectionObserver === Mock;
global.IntersectionObserver === Mock;
globalThis.IntersectionObserver === Mock;
// jsdom 또는 happy-dom을 사용하는 경우
window.IntersectionObserver === Mock;

vi.unstubAllGlobals();

globalThis.IntersectionObserver === undefined;
'IntersectionObserver' in globalThis === false;
// 정의되지 않았으므로 ReferenceError를 발생시킵니다.
IntersectionObserver === undefined;

가짜 타이머 ​

이 섹션에서는 가짜 타이머를 사용하는 방법을 설명합니다.

vi.advanceTimersByTime ​

  • 타입: (ms: number) => Vitest

이 메서드는 지정된 밀리초만큼 시간이 경과하도록 타이머를 진행시키거나, 타이머 큐가 빌 때까지 타이머를 실행합니다. (둘 중 먼저 발생하는 것을 기준으로 합니다.)

ts
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => console.log(++i), 50);

vi.advanceTimersByTime(150);

// log: 1
// log: 2
// log: 3

vi.advanceTimersByTimeAsync ​

  • 타입: (ms: number) => Promise<Vitest>

이 메서드는 지정된 밀리초만큼 시간이 경과하도록 타이머를 진행시키거나, 타이머 큐가 빌 때까지 타이머를 실행합니다. (둘 중 먼저 발생하는 것을 기준으로 합니다.) 비동기적으로 설정된 타이머도 포함됩니다.

ts
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);

await vi.advanceTimersByTimeAsync(150);

// log: 1
// log: 2
// log: 3

vi.advanceTimersToNextTimer ​

  • 타입: () => Vitest

다음으로 실행될 예정인 타이머를 실행합니다. 각 타이머 호출 사이에 단언(assertion)을 수행하는 데 유용하며, 체이닝 방식으로 호출하여 타이머를 직접 관리할 수 있습니다.

ts
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => console.log(++i), 50);

vi.advanceTimersToNextTimer() // log: 1
  .advanceTimersToNextTimer() // log: 2
  .advanceTimersToNextTimer(); // log: 3

vi.advanceTimersToNextTimerAsync ​

  • 타입: () => Promise<Vitest>

다음으로 실행될 예정인 타이머를 실행하고, 비동기적으로 설정된 경우 완료될 때까지 기다립니다. 각 타이머 호출 사이에 단언(assertion)을 수행하는 데 유용합니다.

ts
import { expect, vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);

await vi.advanceTimersToNextTimerAsync(); // log: 1
expect(console.log).toHaveBeenCalledWith(1);

await vi.advanceTimersToNextTimerAsync(); // log: 2
await vi.advanceTimersToNextTimerAsync(); // log: 3

vi.getTimerCount ​

  • 타입: () => number

현재 대기 중인 타이머의 개수를 반환합니다.

vi.clearAllTimers ​

실행되도록 예약된 모든 타이머를 제거합니다. 제거된 타이머는 더 이상 실행되지 않습니다.

vi.getMockedSystemTime ​

  • 타입: () => Date | null

setSystemTime을 사용하여 설정된 모의(mocked) 시스템 시간을 반환합니다. 시스템 시간이 모의되지 않은 경우 null을 반환합니다.

vi.getRealSystemTime ​

  • 타입: () => number

vi.useFakeTimers를 사용하는 경우 Date.now 호출이 모의됩니다. 실제 시간을 밀리초 단위로 가져와야 하는 경우 이 함수를 호출할 수 있습니다.

vi.runAllTicks ​

  • 타입: () => Vitest

process.nextTick에 의해 큐에 추가된 모든 마이크로태스크를 실행합니다. 또한, 실행 중에 예약된 모든 마이크로태스크도 실행합니다.

vi.runAllTimers ​

  • 타입: () => Vitest

타이머 큐가 빌 때까지 시작된 모든 타이머를 실행합니다. 즉, runAllTimers 실행 중에 호출된 모든 타이머도 실행됩니다. 무한 간격으로 설정된 타이머가 있는 경우, 10,000번 시도 후 오류가 발생합니다 (fakeTimers.loopLimit로 구성 가능).

ts
import { vi } from 'vitest';
// ---cut---
let i = 0;
setTimeout(() => console.log(++i));
const interval = setInterval(() => {
  console.log(++i);
  if (i === 3) clearInterval(interval);
}, 50);

vi.runAllTimers();

// log: 1
// log: 2
// log: 3

vi.runAllTimersAsync ​

  • 타입: () => Promise<Vitest>

타이머 큐가 빌 때까지 시작된 모든 타이머를 비동기적으로 실행합니다. 즉, runAllTimersAsync 실행 중에 호출된 모든 타이머(비동기 타이머 포함)도 실행됩니다. 무한 간격으로 설정된 타이머가 있는 경우, 10,000번 시도 후 오류가 발생합니다 (fakeTimers.loopLimit로 구성 가능).

ts
import { vi } from 'vitest';
// ---cut---
setTimeout(async () => {
  console.log(await Promise.resolve('result'));
}, 100);

await vi.runAllTimersAsync();

// log: result

vi.runOnlyPendingTimers ​

  • 타입: () => Vitest

vi.useFakeTimers 호출 이후에 시작된 모든 타이머를 실행합니다. 실행 중에 시작된 타이머는 실행하지 않습니다.

ts
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => console.log(++i), 50);

vi.runOnlyPendingTimers();

// log: 1

vi.runOnlyPendingTimersAsync ​

  • 타입: () => Promise<Vitest>

vi.useFakeTimers 호출 이후에 시작된 모든 타이머를 비동기적으로 실행합니다 (비동기 타이머 포함). 실행 중에 시작된 타이머는 실행하지 않습니다.

ts
import { vi } from 'vitest';
// ---cut---
setTimeout(() => {
  console.log(1);
}, 100);
setTimeout(() => {
  Promise.resolve().then(() => {
    console.log(2);
    setInterval(() => {
      console.log(3);
    }, 40);
  });
}, 10);

await vi.runOnlyPendingTimersAsync();

// log: 2
// log: 3
// log: 3
// log: 1

vi.setSystemTime ​

  • 타입: (date: string | number | Date) => void

가짜 타이머가 활성화된 경우, 이 메서드는 시스템 시계를 변경하는 것과 같은 효과를 냅니다. (hrtime, performance.now 또는 new Date()와 같은 날짜 관련 API에 영향을 줍니다.) 하지만 타이머를 진행시키지는 않습니다. 가짜 타이머가 활성화되지 않은 경우, 이 메서드는 Date.* 호출만 모의합니다.

현재 날짜에 따라 달라지는 항목 (예: 코드 내부의 Luxon 호출)을 테스트해야 하는 경우에 유용합니다.

ts
import { expect, vi } from 'vitest';
// ---cut---
const date = new Date(1998, 11, 19);

vi.useFakeTimers();
vi.setSystemTime(date);

expect(Date.now()).toBe(date.valueOf());

vi.useRealTimers();

vi.useFakeTimers ​

  • 타입: (config?: FakeTimerInstallOpts) => Vitest

타이머 모의를 활성화하려면 이 메서드를 호출해야 합니다. vi.useRealTimers()가 호출될 때까지 타이머에 대한 모든 후속 호출 (setTimeout, setInterval, clearTimeout, clearInterval, setImmediate, clearImmediate 및 Date와 같은)을 래핑합니다.

--pool=forks 옵션으로 node:child_process 내에서 Vitest를 실행하는 경우, nextTick 모의는 지원되지 않습니다. NodeJS는 node:child_process 내부적으로 process.nextTick을 사용하며, 이것이 모의되면 프로세스가 멈추게 됩니다. --pool=threads 옵션으로 Vitest를 실행하면 nextTick 모의가 지원됩니다.

구현은 내부적으로 @sinonjs/fake-timers를 기반으로 합니다.

TIP

0.35.0 버전부터 vi.useFakeTimers()는 더 이상 자동으로 process.nextTick을 모의하지 않습니다. toFake 인수에 옵션을 지정하여 여전히 모의할 수 있습니다. 예: vi.useFakeTimers({ toFake: ['nextTick'] }).

vi.isFakeTimers 0.34.5+ ​

  • 타입: () => boolean

가짜 타이머가 활성화된 경우 true를 반환합니다.

vi.useRealTimers ​

  • 타입: () => Vitest

타이머 모의를 해제하고 모의된 타이머를 원래 구현으로 되돌리려면 이 메서드를 호출합니다. 이전에 예약된 모든 타이머는 삭제됩니다.

기타 ​

Vitest에서 제공하는 유용한 유틸리티 함수 세트입니다.

vi.waitFor 0.34.5+ ​

  • 타입: <T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>

콜백이 성공적으로 실행될 때까지 기다립니다. 콜백에서 오류가 발생하거나 거부(rejected)된 프로미스를 반환하면 성공하거나 시간 초과될 때까지 계속 재시도합니다.

이는 일부 비동기 작업이 완료될 때까지 기다려야 하는 경우 (예: 서버를 시작하고 시작될 때까지 기다리는 경우) 매우 유용합니다.

ts
import { expect, test, vi } from 'vitest';
import { createServer } from './server.js';

test('Server started successfully', async () => {
  const server = createServer();

  await vi.waitFor(
    () => {
      if (!server.isReady) throw new Error('Server not started');

      console.log('Server started');
    },
    {
      timeout: 500, // default is 1000
      interval: 20, // default is 50
    }
  );
  expect(server.isReady).toBe(true);
});

비동기 콜백에도 사용할 수 있습니다.

ts
// @vitest-environment jsdom

import { expect, test, vi } from 'vitest';
import { getDOMElementAsync, populateDOMAsync } from './dom.js';

test('Element exists in a DOM', async () => {
  // start populating DOM
  populateDOMAsync();

  const element = await vi.waitFor(
    async () => {
      // try to get the element until it exists
      const element = (await getDOMElementAsync()) as HTMLElement | null;
      expect(element).toBeTruthy();
      expect(element.dataset.initialized).toBeTruthy();
      return element;
    },
    {
      timeout: 500, // default is 1000
      interval: 20, // default is 50
    }
  );
  expect(element).toBeInstanceOf(HTMLElement);
});

vi.useFakeTimers가 사용되는 경우 vi.waitFor는 각 검사 콜백에서 자동으로 vi.advanceTimersByTime(interval)을 호출합니다.

vi.waitUntil 0.34.5+ ​

  • 타입: <T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>

vi.waitFor와 유사하지만, 콜백에서 오류가 발생하면 즉시 실행이 중단되고 오류 메시지가 표시됩니다. 콜백에서 falsy 값을 반환하면 truthy 값이 반환될 때까지 다음 검사를 반복합니다. 특정 조건이 충족될 때까지 기다려야 하는 경우에 유용합니다.

아래 예제에서 vi.waitUntil을 사용하여 페이지에 요소가 나타날 때까지 기다린 다음, 해당 요소에 대한 작업을 수행하는 방법을 보여줍니다.

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

test('Element render correctly', async () => {
  const element = await vi.waitUntil(() => document.querySelector('.element'), {
    timeout: 500, // default is 1000
    interval: 20, // default is 50
  });

  // do something with the element
  expect(element.querySelector('.element-child')).toBeTruthy();
});

vi.hoisted 0.31.0+ ​

  • 타입: <T>(factory: () => T) => T

ES 모듈에서 정적으로 선언된 모든 import 구문은 파일의 최상단으로 호이스팅됩니다. 따라서 import 구문보다 먼저 정의된 코드는, 실제로는 import 구문이 평가된 후에 실행됩니다.

그러나 모듈을 가져오기 전에 날짜 모의와 같은 사이드 이펙트(side effect)를 발생시키는 것이 유용한 경우가 있습니다.

이러한 제한 사항을 해결하려면 정적 가져오기를 다음과 같이 동적 가져오기로 변경할 수 있습니다.

diff
callFunctionWithSideEffect()
- import { value } from './some/module.js'
+ const { value } = await import('./some/module.js')

vitest를 실행할 때 vi.hoisted 메서드를 사용하여 이를 자동으로 처리할 수 있습니다.

diff
- callFunctionWithSideEffect()
import { value } from './some/module.js'
+ vi.hoisted(() => callFunctionWithSideEffect())

이 메서드는 팩토리 함수에서 반환된 값을 반환합니다. 로컬에 정의된 변수에 쉽게 액세스해야 하는 경우, 해당 값을 vi.mock 팩토리 함수에서 사용할 수 있습니다.

ts
import { expect, vi } from 'vitest';
import { originalMethod } from './path/to/module.js';

const { mockedMethod } = vi.hoisted(() => {
  return { mockedMethod: vi.fn() };
});

vi.mock('./path/to/module.js', () => {
  return { originalMethod: mockedMethod };
});

mockedMethod.mockReturnValue(100);
expect(originalMethod()).toBe(100);

환경에서 최상위 await를 지원하지 않더라도 이 메서드를 비동기적으로 호출할 수 있습니다.

ts
const promised = await vi.hoisted(async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  return response.json();
});

vi.setConfig ​

  • 타입: RuntimeConfig

현재 테스트 파일에 대한 구성을 업데이트합니다. 이 메서드는 현재 테스트 파일에 영향을 미치는 구성 옵션만 지원합니다.

ts
vi.setConfig({
  allowOnly: true,
  testTimeout: 10_000,
  hookTimeout: 10_000,
  clearMocks: true,
  restoreMocks: true,
  fakeTimers: {
    now: new Date(2021, 11, 19),
    // supports the whole object
  },
  maxConcurrency: 10,
  sequence: {
    hooks: 'stack',
    // supports only "sequence.hooks"
  },
});

vi.resetConfig ​

  • 타입: RuntimeConfig

vi.setConfig이 호출된 적이 있다면, 설정을 초기 상태로 되돌립니다.

Pager
이전Mock 함수
다음expect

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2024 Mithril Contributors

https://v1.vitest.dev/api/vi

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2024 Mithril Contributors