Vi
Vitest는 vi
헬퍼를 통해 유틸리티 기능을 제공합니다. 전역적으로 접근하거나 (globals configuration이 활성화된 경우), vitest
에서 가져올 수 있습니다.
import { vi } from 'vitest';
vi.advanceTimersByTime
타입:
(ms: number) => Vitest
runAllTimers
와 동일하게 작동하지만, 지정된 밀리초만큼 시간이 경과한 후 종료됩니다. 예를 들어, 다음 코드는1, 2, 3
을 기록하고 오류를 발생시키지 않습니다.tslet i = 0; setInterval(() => console.log(++i), 50); vi.advanceTimersByTime(150);
vi.advanceTimersByTimeAsync
타입:
(ms: number) => Promise<Vitest>
runAllTimersAsync
와 동일하게 작동하지만, 지정된 밀리초만큼 시간이 경과한 후 종료됩니다. 비동기적으로 설정된 타이머도 포함됩니다. 예를 들어, 다음 코드는1, 2, 3
을 기록하고 오류를 발생시키지 않습니다.tslet i = 0; setInterval(() => Promise.resolve().then(() => console.log(++i)), 50); await vi.advanceTimersByTimeAsync(150);
vi.advanceTimersToNextTimer
타입:
() => Vitest
다음으로 실행될 타이머를 실행합니다. 각 타이머 실행 사이에 assertion을 수행하는 데 유용합니다. 메서드 체이닝을 통해 타이머를 직접 관리할 수 있습니다.
tslet i = 0; setInterval(() => console.log(++i), 50); vi.advanceTimersToNextTimer() // log 1 .advanceTimersToNextTimer() // log 2 .advanceTimersToNextTimer(); // log 3
vi.advanceTimersToNextTimerAsync
타입:
() => Promise<Vitest>
비동기적으로 설정된 타이머를 포함하여 다음으로 실행될 타이머를 실행합니다. 각 타이머 실행 사이에 assertion을 수행하는 데 유용합니다. 메서드 체이닝을 통해 타이머를 직접 관리할 수 있습니다.
tslet i = 0; setInterval(() => Promise.resolve().then(() => console.log(++i)), 50); vi.advanceTimersToNextTimerAsync() // log 1 .advanceTimersToNextTimerAsync() // log 2 .advanceTimersToNextTimerAsync(); // log 3
vi.getTimerCount
타입:
() => number
현재 대기 중인 타이머의 수를 반환합니다.
vi.clearAllMocks
모든 스파이(spy)에서 .mockClear()
를 호출합니다. 이는 mock 히스토리를 초기화하지만, 구현은 기본값으로 재설정하지 않습니다.
vi.clearAllTimers
실행되도록 예약된 모든 타이머를 제거합니다. 제거된 타이머는 더 이상 실행되지 않습니다.
vi.dynamicImportSettled
모든 import가 완료될 때까지 기다립니다. 모듈을 동기적으로 import하는 호출이 있을 때, 다른 방법으로는 완료를 기다릴 수 없는 경우 유용합니다.
vi.fn
타입:
(fn?: Function) => Mock
함수에 대한 스파이(spy) 함수를 생성합니다. 함수 없이 초기화할 수도 있습니다. 함수가 호출될 때마다 호출 인수, 반환 값 및 인스턴스를 저장합니다. 또한 메서드를 사용하여 동작을 조작할 수 있습니다. 함수가 제공되지 않으면 mock은 호출될 때
undefined
를 반환합니다.tsconst 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.getMockedSystemTime
타입:
() => Date | null
setSystemTime
을 사용하여 설정된 mock 현재 날짜를 반환합니다. 날짜가 mock되지 않은 경우null
을 반환합니다.
vi.getRealSystemTime
타입:
() => number
vi.useFakeTimers
를 사용하는 경우Date.now
호출이 mock됩니다. 밀리초 단위의 실제 시간을 가져와야 하는 경우 이 함수를 호출할 수 있습니다.
vi.hoisted
타입:
<T>(factory: () => T) => T
버전: Vitest 0.31.0 이후
ES 모듈의 모든 정적
import
문은 파일 맨 위로 호이스팅(hoisting)되므로, import문 전에 정의된 코드는 실제로 import문이 평가된 후에 실행됩니다.그러나 모듈을 import하기 전에 날짜를 mock하는 것과 같이 특정 부작용을 발생시키는 것이 유용할 수 있습니다.
이러한 제한 사항을 해결하려면 정적 import를 다음과 같이 동적 import로 다시 작성할 수 있습니다.
diffcallFunctionWithSideEffect() - import { value } from './some/module.ts' + const { value } = await import('./some/module.ts')
vitest
를 실행할 때vi.hoisted
메서드를 사용하여 이를 자동으로 수행할 수 있습니다.diff- callFunctionWithSideEffect() import { value } from './some/module.ts' + vi.hoisted(() => callFunctionWithSideEffect())
이 메서드는 팩토리 함수에서 반환된 값을 반환합니다. 로컬로 정의된 변수에 쉽게 접근해야 하는 경우
vi.mock
팩토리 함수에서 해당 값을 사용할 수 있습니다.tsimport { 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);
vi.mock
타입:
(path: string, factory?: () => unknown) => void
지정된
path
에서 import된 모든 모듈을 다른 모듈로 대체합니다. 경로 내에서 구성된 Vite 별칭을 사용할 수 있습니다.vi.mock
에 대한 호출은 호이스팅(hoisting)되므로 호출 위치는 중요하지 않습니다. 항상 모든 import 전에 실행됩니다. 스코프 밖의 변수를 참조해야 하는 경우,vi.hoisted
내부에 변수를 정의하고vi.mock
내부에서 참조할 수 있습니다.WARNING
vi.mock
은import
키워드로 import된 모듈에만 작동합니다.require
에서는 작동하지 않습니다.Vitest는
vi.mock
을 호이스팅(hoisting)하기 위해 파일을 정적으로 분석합니다. 즉,vitest
패키지에서 직접 import되지 않은vi
(예: 일부 유틸리티 파일에서)는 사용할 수 없습니다. 이를 해결하려면 항상vitest
에서 import된vi
와 함께vi.mock
을 사용하거나globals
구성 옵션을 활성화하십시오.factory
가 정의된 경우 모든 import는 해당 결과를 반환합니다. Vitest는 팩토리 함수를 한 번만 호출하고vi.unmock
또는vi.doUnmock
이 호출될 때까지 모든 후속 import에 대해 결과를 캐시합니다.jest
와 달리 팩토리 함수는 비동기적일 수 있으므로vi.importActual
또는 첫 번째 인수로 받은 헬퍼를 내부에서 사용하여 원래 모듈을 가져올 수 있습니다.tsvi.mock('./path/to/module.js', async importOriginal => { const mod = await importOriginal(); return { ...mod, // replace some exports namedExport: vi.fn(), }; });
WARNING
vi.mock
은 파일의 최상단으로 호이스팅(hoisting)됩니다 (즉, 끌어올려집니다). 즉, 작성하는 위치 (예:beforeEach
또는test
내부)에 관계없이 실제로 그 전에 호출됩니다.이는 또한 팩토리 함수 외부에서 정의된 변수를 팩토리 함수 내부에서 사용할 수 없음을 의미합니다.
팩토리 함수 내부에서 변수를 사용해야 하는 경우
vi.doMock
을 사용해 보십시오. 동일한 방식으로 작동하지만 호이스팅(hoisting)되지 않습니다. 이후 import만 mock합니다.vi.mock
전에 선언된 경우vi.hoisted
메서드에 의해 정의된 변수를 참조할 수도 있습니다.tsimport { 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를 사용하는 모듈을 mock하는 경우, 반환되는 팩토리 함수 객체 내에
default
키를 반드시 포함해야 합니다. 이는 ES 모듈 관련 주의 사항이므로jest
는 CommonJS 모듈을 사용하므로jest
설명서와 다를 수 있습니다. 예를 들어,tsvi.mock('./path/to/module.js', () => { return { default: { myDefaultKey: vi.fn() }, namedExport: vi.fn(), // etc... }; });
mock하려는 파일과 함께
__mocks__
폴더가 있고 팩토리 함수가 제공되지 않은 경우 Vitest는__mocks__
하위 폴더에서 동일한 이름의 파일을 찾아 실제 모듈로 사용하려고 시도합니다. 종속성을 mock하는 경우 Vitest는 프로젝트의 루트 (기본값은process.cwd()
)에서__mocks__
폴더를 찾으려고 시도합니다. deps.moduleDirectories 구성 옵션을 통해 Vitest에 종속성이 있는 위치를 알릴 수 있습니다.예를 들어, 다음과 같은 파일 구조가 있습니다.
- __mocks__ - axios.js - src __mocks__ - increment.js - increment.js - tests - increment.test.js
팩토리 함수가 제공되지 않은 테스트 파일에서
vi.mock
을 호출하면 모듈로 사용할__mocks__
폴더에서 파일을 찾습니다.ts// increment.test.js import { vi } from 'vitest'; // axios는 `__mocks__/axios.js`의 기본 내보내기(default export)입니다. import axios from 'axios'; // increment는 `src/__mocks__/increment.js`의 명명된 내보내기(named export)입니다. import { increment } from '../increment.js'; vi.mock('axios'); vi.mock('../increment.js'); axios.get(`/apples/${increment(1)}`);
WARNING
vi.mock
을 호출하지 않으면 모듈이 자동으로 mock되지 않습니다. Jest의 자동 mock 동작을 복제하려면setupFiles
내에서 필요한 각 모듈에 대해vi.mock
을 호출할 수 있습니다.__mocks__
폴더 또는 제공된 팩토리 함수가 없는 경우 Vitest는 원래 모듈을 import하고 모든 내보내기(export)를 자동으로 mock합니다. 적용되는 규칙은 알고리즘을 참조하십시오.
vi.doMock
타입:
(path: string, factory?: () => unknown) => void
vi.mock
과 동일하지만 파일 맨 위로 호이스팅(hoisting)되지 않으므로 전역 파일 스코프에서 변수를 참조할 수 있습니다. 이후의 동적 import는 mock됩니다. 이는 이 호출 전에 import된 모듈은 mock하지 않습니다.
// ./increment.js
export function increment(number) {
return number + 1;
}
import { beforeEach, test } from 'vitest';
import { increment } from './increment.js';
// vi.doMock이 아직 호출되지 않았으므로 모듈이 mock되지 않았습니다.
increment(1) === 2;
let mockedIncrement = 100;
beforeEach(() => {
// 팩토리 함수 내부에서 변수에 접근할 수 있습니다.
vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});
test('다음 모듈 import는 mock된 모듈을 import합니다.', async () => {
// 원래 import는 `vi.doMock` 호출 이후에 평가되기 때문에 mock되지 않았습니다.
expect(increment(1)).toBe(2);
const { increment: mockedIncrement } = await import('./increment.js');
// 새로운 동적 import는 mock된 모듈을 반환합니다.
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>
를 반환 값으로 예상합니다.tsimport example from './example.js'; vi.mock('./example.js'); test('1 + 1은 2와 같습니다.', async () => { vi.mocked(example.calc).mockRestore(); const res = example.calc(1, '+', 1); expect(res).toBe(2); });
vi.importActual
타입:
<T>(path: string) => Promise<T>
모듈을 import할 때 mock 여부에 대한 검사를 건너뜁니다. 모듈을 부분적으로 mock하려는 경우 유용할 수 있습니다.
tsvi.mock('./example.js', async () => { const axios = await vi.importActual('./example.js'); return { ...axios, get: vi.fn() }; });
vi.importMock
타입:
<T>(path: string) => Promise<MaybeMockedDeep<T>>
모든 속성 (중첩된 속성 포함)이 mock된 모듈을 import합니다.
vi.mock
과 동일한 규칙을 따릅니다. 적용되는 규칙은 알고리즘을 참조하십시오.
vi.resetAllMocks
모든 스파이(spy)에서 .mockReset()
을 호출합니다. 이렇게 하면 mock 히스토리가 지워지고 구현이 빈 함수로 초기화됩니다 ( undefined
반환).
vi.resetConfig
타입:
RuntimeConfig
vi.setConfig
이 이전에 호출된 경우 설정을 원래 상태로 되돌립니다.
vi.resetModules
타입:
() => Vitest
모든 모듈의 캐시를 삭제하여 모듈 레지스트리를 초기화합니다. 이렇게 하면 모듈을 다시 import할 때 모듈을 다시 평가할 수 있습니다. 최상위 import는 다시 평가할 수 없습니다. 로컬 상태가 테스트 간에 충돌하는 모듈을 격리하는 데 유용할 수 있습니다.
tsimport { vi } from 'vitest'; import { data } from './data.js'; // beforeEach 테스트에서 다시 평가되지 않습니다. 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
mock 레지스트리를 재설정하지 않습니다. mock 레지스트리를 지우려면 vi.unmock
또는 vi.doUnmock
을 사용하십시오.
vi.restoreAllMocks
모든 스파이(spy)에서 .mockRestore()
을 호출합니다. 이렇게 하면 mock 히스토리가 지워지고 구현이 원래 상태로 재설정됩니다.
vi.stubEnv
타입:
(name: string, value: string) => Vitest
버전: Vitest 0.26.0 이후
process.env
및import.meta.env
에서 환경 변수의 값을 변경합니다.vi.unstubAllEnvs
를 호출하면 값을 복원할 수 있습니다.
import { vi } from 'vitest';
// `process.env.NODE_ENV` 및 `import.meta.env.NODE_ENV`
// `vi.stubEnv` 호출 전에는 "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
를 사용하여 이전 값을 복원할 수는 없습니다.
import.meta.env.MODE = 'test';
vi.unstubAllEnvs
타입:
() => Vitest
버전: Vitest 0.26.0 이후
vi.stubEnv
를 통해 변경된 모든import.meta.env
및process.env
값을 원래 값으로 복원합니다.unstubAllEnvs
가 처음 호출될 때 Vitest는 현재 값을 저장하고, 이후unstubAllEnvs
가 호출될 때 저장된 값으로 되돌립니다.
import { vi } from 'vitest';
// `process.env.NODE_ENV` 및 `import.meta.env.NODE_ENV`
// stubEnv 호출 전에는 "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
를 호출하여 원래 값으로 복원할 수 있습니다.
import { vi } from 'vitest';
// `innerWidth`는 `stubGlobal` 호출 전에는 "0"입니다.
vi.stubGlobal('innerWidth', 100);
innerWidth === 100;
globalThis.innerWidth === 100;
// jsdom 또는 happy-dom을 사용하는 경우
window.innerWidth === 100;
TIP
globalThis
또는 window
( jsdom
또는 happy-dom
환경을 사용하는 경우)에 직접 값을 할당하여 변경할 수도 있지만, 이 경우 vi.unstubAllGlobals
를 사용하여 원래 값을 복원할 수 없습니다.
globalThis.innerWidth = 100;
// jsdom 또는 happy-dom을 사용하는 경우
window.innerWidth = 100;
vi.unstubAllGlobals
타입:
() => Vitest
버전: Vitest 0.26.0 이후
vi.stubGlobal
을 통해 변경된globalThis
/global
(및window
/top
/self
/parent
,jsdom
또는happy-dom
환경을 사용하는 경우)의 모든 전역 값을 원래 값으로 복원합니다.unstubAllGlobals
가 처음 호출될 때 Vitest는 현재 값을 저장하고, 이후unstubAllGlobals
가 호출될 때 저장된 값으로 되돌립니다.
import { vi } from 'vitest';
const Mock = vi.fn();
// IntersectionObserver는 "stubGlobal" 호출 전에는 "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.runAllTicks
타입:
() => Vitest
process.nextTick
을 통해 큐에 추가된 모든 마이크로태스크를 실행합니다. 이는 또한 자체적으로 예약된 모든 마이크로태스크도 실행합니다.
vi.runAllTimers
타입:
() => Vitest
이 메서드는 타이머 큐가 빌 때까지 보류 중인 모든 타이머를 실행합니다. 즉,
runAllTimers
실행 중에 예약된 타이머도 실행됩니다. 무한 간격으로 설정된 타이머가 있는 경우, 10,000번 시도 후 오류가 발생합니다. 다음은1, 2, 3
을 콘솔에 출력하는 예제입니다.tslet i = 0; setTimeout(() => console.log(++i)); const interval = setInterval(() => { console.log(++i); if (i === 3) clearInterval(interval); }, 50); vi.runAllTimers();
vi.runAllTimersAsync
타입:
() => Promise<Vitest>
이 메서드는 타이머 큐가 빌 때까지 보류 중인 모든 타이머를 비동기적으로 실행합니다. 즉,
runAllTimersAsync
실행 중에 예약된 비동기 타이머도 실행됩니다. 무한 간격으로 설정된 타이머가 있는 경우, 10,000번 시도 후 오류가 발생합니다. 다음은result
를 콘솔에 출력하는 예제입니다.tssetTimeout(async () => { console.log(await Promise.resolve('result')); }, 100); await vi.runAllTimersAsync();
vi.runOnlyPendingTimers
타입:
() => Vitest
이 메서드는
vi.useFakeTimers()
호출 이후에 예약된 모든 타이머를 실행합니다. 실행 중에 예약된 타이머는 실행되지 않습니다. 다음은1
만 콘솔에 출력하는 예제입니다.tslet i = 0; setInterval(() => console.log(++i), 50); vi.runOnlyPendingTimers();
vi.runOnlyPendingTimersAsync
타입:
() => Promise<Vitest>
이 메서드는
vi.useFakeTimers()
호출 이후에 예약된 모든 타이머를 비동기적으로 실행합니다 (비동기 타이머 포함). 실행 중에 예약된 타이머는 실행되지 않습니다. 다음은2, 3, 3, 1
을 콘솔에 출력하는 예제입니다.tssetTimeout(() => { console.log(1); }, 100); setTimeout(() => { Promise.resolve().then(() => { console.log(2); setInterval(() => { console.log(3); }, 40); }); }, 10); await vi.runOnlyPendingTimersAsync();
vi.setSystemTime
타입:
(date: string | number | Date) => void
시스템 시간을 지정된 날짜로 설정합니다. 이후 모든
Date
호출은 이 날짜를 기준으로 합니다.코드 내부에서 luxon과 같이 현재 시간에 의존하는 로직을 테스트할 때 유용합니다.
tsconst date = new Date(1998, 11, 19); vi.useFakeTimers(); vi.setSystemTime(date); expect(Date.now()).toBe(date.valueOf()); vi.useRealTimers();
vi.setConfig
타입:
RuntimeConfig
현재 테스트 파일의 설정을 업데이트합니다. 이 설정은 테스트 실행 시에만 적용됩니다.
vi.spyOn
타입:
<T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance
객체의 메서드 또는 getter/setter에 대한 스파이 함수를 생성합니다.
tslet apples = 0; const cart = { getApples: () => 13, }; const spy = vi.spyOn(cart, 'getApples').mockImplementation(() => apples); apples = 1; expect(cart.getApples()).toBe(1); expect(spy).toHaveBeenCalled(); expect(spy).toHaveReturnedWith(1);
vi.stubGlobal
타입:
(key: keyof globalThis & Window, value: any) => Vitest
전역 변수에 값을 할당합니다.
jsdom
또는happy-dom
을 사용하는 경우window
객체에도 값을 할당합니다.자세한 내용은 "전역 모의" 섹션을 참조하십시오.
vi.unmock
타입:
(path: string) => void
모의(mock) 레지스트리에서 모듈을 제거합니다. 이후 해당 모듈에 대한 import는 이전에 모의되었더라도 원래 모듈을 반환합니다. 이 호출은 호이스팅되어 파일 맨 위로 이동하므로, 예를 들어
setupFiles
에 정의된 모듈만 언모킹됩니다.
vi.doUnmock
타입:
(path: string) => void
vi.unmock
과 동일하지만 파일의 맨 위로 호이스팅되지 않습니다. 다음에 해당 모듈을 import하면 모의된 모듈 대신 실제 모듈을 가져옵니다. 이미 가져온 모듈은 언모킹되지 않습니다.
// ./increment.js
export function increment(number) {
return number + 1;
}
import { increment } from './increment.js';
// increment는 vi.mock이 호이스팅되기 때문에 이미 모의되었습니다.
increment(1) === 100;
// 이는 호이스팅되고 팩토리는 1행의 가져오기 전에 호출됩니다.
vi.mock('./increment.js', () => ({ increment: () => 100 }));
// 모든 호출이 모의되고 `increment`는 항상 100을 반환합니다.
increment(1) === 100;
increment(30) === 100;
// 이는 호이스팅되지 않으므로 다른 가져오기는 언모킹된 모듈을 반환합니다.
vi.doUnmock('./increment.js');
// 이는 `vi.doUnmock`이 모듈을 다시 평가하지 않기 때문에 여전히 100을 반환합니다.
increment(1) === 100;
increment(30) === 100;
// 다음 가져오기는 언모킹되었으며 이제 `increment`는 count + 1을 반환하는 원래 함수입니다.
const { increment: unmockedIncrement } = await import('./increment.js');
unmockedIncrement(1) === 2;
unmockedIncrement(30) === 31;
vi.useFakeTimers
타입:
() => Vitest
타이머 모의를 활성화하려면 이 메서드를 호출해야 합니다. 이 메서드는
vi.useRealTimers()
가 호출될 때까지 타이머(setTimeout
,setInterval
,clearTimeout
,clearInterval
,nextTick
,setImmediate
,clearImmediate
및Date
등)에 대한 모든 후속 호출을 래핑합니다.--no-threads
를 사용하여node:child_process
내부에서 Vitest를 실행할 때는nextTick
모의가 지원되지 않습니다. NodeJS는node:child_process
에서 내부적으로process.nextTick
을 사용하며, 모의되면 중단됩니다.--threads
를 사용하여 Vitest를 실행할 때는nextTick
모의가 지원됩니다.구현은 내부적으로
@sinonjs/fake-timers
를 기반으로 합니다.TIP
0.35.0
버전부터vi.useFakeTimers()
는 더 이상 자동으로process.nextTick
을 모의하지 않습니다.toFake
인수에 옵션을 지정하여 여전히 모의할 수 있습니다. 예:vi.useFakeTimers({ toFake: ['nextTick'] })
.
vi.isFakeTimers
타입:
() => boolean
버전: Vitest 0.34.5 이후
가짜 타이머가 활성화된 경우
true
를 반환합니다.
vi.useRealTimers
타입:
() => Vitest
타이머 모의 사용이 끝나면 이 메서드를 호출하여 모의된 타이머를 실제 구현으로 되돌릴 수 있습니다. 이전에 실행된 모든 타이머는 복원되지 않습니다.
vi.waitFor
- 타입:
<T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>
- 버전: Vitest 0.34.5 이후
콜백 함수가 성공적으로 실행될 때까지 기다립니다. 콜백 함수가 오류를 발생시키거나, 거부된 Promise를 반환하면 성공하거나 시간 초과될 때까지 계속 재시도합니다.
이는 예를 들어 서버를 시작하고 시작될 때까지 기다려야 하는 경우와 같이 비동기 작업이 완료될 때까지 기다려야 할 때 유용합니다.
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, // 기본값은 1000입니다.
interval: 20, // 기본값은 50입니다.
}
);
expect(server.isReady).toBe(true);
});
비동기 콜백에도 사용할 수 있습니다.
// @vitest-environment jsdom
import { expect, test, vi } from 'vitest';
import { getDOMElementAsync, populateDOMAsync } from './dom.js';
test('Element exists in a DOM', async () => {
// DOM 채우기 시작
populateDOMAsync();
const element = await vi.waitFor(
async () => {
// 요소가 존재할 때까지 가져오려고 시도합니다.
const element = (await getDOMElementAsync()) as HTMLElement | null;
expect(element).toBeTruthy();
expect(element.dataset.initialized).toBeTruthy();
return element;
},
{
timeout: 500, // 기본값은 1000입니다.
interval: 20, // 기본값은 50입니다.
}
);
expect(element).toBeInstanceOf(HTMLElement);
});
vi.useFakeTimers
가 사용되는 경우 vi.waitFor
는 각 검사 콜백에서 자동으로 vi.advanceTimersByTime(interval)
을 호출합니다.
vi.waitUntil
- 타입:
<T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>
- 버전: Vitest 0.34.5 이후
vi.waitFor
와 유사하지만 콜백이 오류를 발생시키면 즉시 실행이 중단되고 오류 메시지가 표시됩니다. 콜백 함수가 falsy 값을 반환하면 truthy 값이 반환될 때까지 다음 검사를 계속합니다. 이는 다음 단계를 수행하기 전에 특정 조건이 충족될 때까지 기다려야 할 때 유용합니다.
다음 예제를 살펴보세요. vi.waitUntil
을 사용하여 페이지에 요소가 나타날 때까지 기다린 다음 해당 요소에 대한 작업을 수행할 수 있습니다.
import { expect, test, vi } from 'vitest';
test('Element render correctly', async () => {
const element = await vi.waitUntil(() => document.querySelector('.element'), {
timeout: 500, // 기본값은 1000입니다.
interval: 20, // 기본값은 50입니다.
});
// 해당 요소에 대한 작업을 수행합니다.
expect(element.querySelector('.element-child')).toBeTruthy();
});