Mock 함수
vi.fn
메서드를 사용하여 실행을 추적하는 Mock 함수를 생성할 수 있습니다. 이미 생성된 객체의 메서드를 추적하려면 vi.spyOn
메서드를 사용할 수 있습니다.
import { vi } from 'vitest';
const fn = vi.fn();
fn('hello world');
fn.mock.calls[0] === ['hello world'];
const market = {
getApples: () => 100,
};
const getApplesSpy = vi.spyOn(market, 'getApples');
market.getApples();
getApplesSpy.mock.calls.length === 1;
모의 함수 결과를 검증하려면 expect
를 사용하고, toHaveBeenCalled
와 같은 mock 단언을 활용하십시오. 이 API 참조는 모의 함수 동작을 제어하는 데 사용할 수 있는 속성과 메서드를 설명합니다.
getMockImplementation
- 타입:
(...args: any) => any
현재 모의 구현이 있다면 반환합니다.
vi.fn
으로 모의 함수가 생성된 경우, 전달된 함수가 모의 구현으로 간주됩니다.
vi.spyOn
으로 모의 함수가 생성된 경우, 사용자 정의 구현이 제공되지 않았다면 undefined
를 반환합니다.
getMockName
- 타입:
() => string
.mockName(name)
메서드로 mock에 지정된 이름을 반환합니다. 모의 함수의 이름을 확인할 때 유용합니다.
mockClear
- 타입:
() => MockInstance
모든 호출에 대한 정보를 지웁니다. 호출 후 .mock
의 모든 속성은 빈 상태를 반환합니다. 이 메서드는 구현을 재설정하지 않으므로, 다른 단언 간에 mock을 초기화해야 하는 경우에 유용합니다.
이 메서드를 각 테스트 전에 자동으로 호출하려면, 구성에서 clearMocks
설정을 활성화하십시오.
mockName
- 타입:
(name: string) => MockInstance
내부 mock 이름을 설정합니다. 단언이 실패할 경우 mock 이름을 확인하는 데 유용합니다.
mockImplementation
- 타입:
(fn: Function) => MockInstance
모의 함수의 구현체로 사용할 함수를 지정합니다.
import { vi } from 'vitest';
// ---cut---
const mockFn = vi.fn().mockImplementation(apples => apples + 1);
// or: vi.fn(apples => apples + 1);
const NelliesBucket = mockFn(0);
const BobsBucket = mockFn(1);
NelliesBucket === 1; // true
BobsBucket === 2; // true
mockFn.mock.calls[0][0] === 0; // true
mockFn.mock.calls[1][0] === 1; // true
mockImplementationOnce
- 타입:
(fn: Function) => MockInstance
다음 호출 시 mock의 구현체로 사용될 함수를 설정합니다. 여러 함수 호출이 서로 다른 결과를 생성하도록 연결할 수 있습니다.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
.fn()
.mockImplementationOnce(() => true)
.mockImplementationOnce(() => false);
myMockFn(); // true
myMockFn(); // false
모의 함수의 구현이 모두 소진되면 vi.fn(() => defaultValue)
또는 .mockImplementation(() => defaultValue)
로 설정된 기본 구현을 호출합니다(호출된 경우).
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
withImplementation
- 타입:
(fn: Function, callback: () => void) => MockInstance
- 타입:
(fn: Function, callback: () => Promise<unknown>) => Promise<MockInstance>
콜백이 실행되는 동안 원래 mock 구현을 일시적으로 재정의합니다.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi.fn(() => 'original');
myMockFn.withImplementation(
() => 'temp',
() => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
비동기 콜백과 함께 사용할 수 있습니다. 나중에 원래 구현을 사용하려면 메서드가 완료될 때까지 기다려야 합니다.
test('async callback', () => {
const myMockFn = vi.fn(() => 'original');
// 콜백이 비동기이므로 이 호출을 기다립니다.
await myMockFn.withImplementation(
() => 'temp',
async () => {
myMockFn(); // 'temp'
}
);
myMockFn(); // 'original'
});
이 메서드는 mockImplementationOnce
보다 우선합니다.
mockRejectedValue
- 타입:
(value: any) => MockInstance
비동기 함수가 호출될 때 거부될 오류를 설정합니다.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws "Async error"
mockRejectedValueOnce
- 타입:
(value: any) => MockInstance
다음 함수 호출 시 거부될 값을 설정합니다. 체이닝하면 각 연속적인 호출은 지정된 값을 reject합니다.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error'));
await asyncMock(); // first call
await asyncMock(); // throws "Async error"
mockReset
- 타입:
() => MockInstance
mockClear
와 동일한 작업을 수행하며, 내부 구현을 호출 시 undefined
를 반환하는 빈 함수로 만듭니다. 또한 모든 "once" 구현을 재설정합니다. 이는 모의 함수를 완전히 초기 상태로 되돌릴 때 유용합니다.
이 메서드를 각 테스트 전에 자동으로 호출하려면, 구성에서 mockReset
설정을 활성화하십시오.
mockRestore
- 타입:
() => MockInstance
mockReset
이 수행하는 작업을 수행하고 내부 구현을 원래 함수로 복원합니다.
vi.fn()
으로 생성된 mock을 복원하면 구현이 undefined
를 반환하는 빈 함수로 설정됩니다. vi.fn(impl)
로 생성된 mock을 복원하면 구현이 impl
로 복원됩니다.
이 메서드를 각 테스트 전에 자동으로 호출하려면, 구성에서 restoreMocks
설정을 활성화하십시오.
mockResolvedValue
- 타입:
(value: any) => MockInstance
비동기 함수가 호출될 때 resolve될 값을 설정합니다.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi.fn().mockResolvedValue(42);
await asyncMock(); // 42
mockResolvedValueOnce
- 타입:
(value: any) => MockInstance
다음 함수 호출 시 resolve될 값을 설정합니다. 연결되면 모든 연속 호출이 지정된 값을 resolve합니다.
import { vi } from 'vitest';
// ---cut---
const asyncMock = vi
.fn()
.mockResolvedValue('default')
.mockResolvedValueOnce('first call')
.mockResolvedValueOnce('second call');
await asyncMock(); // first call
await asyncMock(); // second call
await asyncMock(); // default
await asyncMock(); // default
mockReturnThis
- 타입:
() => MockInstance
실제 구현을 호출하지 않고 메서드에서 this
컨텍스트를 반환해야 하는 경우에 사용합니다. 이는 다음의 축약 표현입니다.
spy.mockImplementation(function () {
return this;
});
mockReturnValue
- 타입:
(value: any) => MockInstance
모의 함수가 호출될 때마다 반환할 값을 설정합니다.
import { vi } from 'vitest';
// ---cut---
const mock = vi.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockReturnValueOnce
- 타입:
(value: any) => MockInstance
다음 함수 호출 시 반환될 값을 설정합니다. 연결되면 모든 연속 호출이 지정된 값을 반환합니다.
사용할 mockReturnValueOnce
값이 더 이상 없으면 mock은 이전에 정의된 구현이 있는 경우 해당 구현으로 대체됩니다.
import { vi } from 'vitest';
// ---cut---
const myMockFn = vi
.fn()
.mockReturnValue('default')
.mockReturnValueOnce('first call')
.mockReturnValueOnce('second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
mock.calls
이는 각 호출에 대한 모든 인수를 포함하는 배열입니다. 배열의 각 항목은 해당 호출의 인수 목록입니다.
const fn = vi.fn();
fn('arg1', 'arg2');
fn('arg3');
fn.mock.calls ===
[
['arg1', 'arg2'], // first call
['arg3'], // second call
];
mock.lastCall
여기에는 마지막 호출의 인수가 포함됩니다. mock이 호출되지 않은 경우 undefined
를 반환합니다.
mock.results
이는 함수에서 반환된 모든 값을 담고 있는 배열입니다. 배열의 각 항목은 type
및 value
속성이 있는 객체입니다. 사용 가능한 유형은 다음과 같습니다.
'return'
- 함수가 예외를 발생시키지 않고 반환되었습니다.'throw'
- 함수가 값을 throw했습니다.
value
속성에는 반환된 값 또는 throw된 오류가 포함됩니다. 함수가 Promise를 반환한 경우, value
는 실제 Promise
객체가 아닌, resolve된 값이 됩니다. 단, Promise가 resolve되지 않은 경우에는 예외입니다.
const fn = vi
.fn()
.mockReturnValueOnce('result')
.mockImplementationOnce(() => {
throw new Error('thrown error');
});
const result = fn(); // returned 'result'
try {
fn(); // threw Error
} catch {}
fn.mock.results ===
[
// first result
{
type: 'return',
value: 'result',
},
// last result
{
type: 'throw',
value: Error,
},
];
mock.invocationCallOrder
mock 실행 순서입니다. 이는 정의된 모든 mock 간에 공유되는 숫자 배열을 반환합니다.
const fn1 = vi.fn();
const fn2 = vi.fn();
fn1();
fn2();
fn1();
fn1.mock.invocationCallOrder === [1, 3];
fn2.mock.invocationCallOrder === [2];
mock.instances
이는 new
키워드를 통해 mock이 호출되어 인스턴스화된 모든 인스턴스를 담고 있는 배열입니다. 이는 반환 값이 아닌 함수의 실제 컨텍스트 (this
)입니다.
WARNING
mock이 new MyClass()
로 인스턴스화된 경우 mock.instances
는 하나의 값을 가진 배열이 됩니다.
const MyClass = vi.fn();
const a = new MyClass();
MyClass.mock.instances[0] === a;
생성자에서 값을 반환하는 경우, 해당 값은 instances
배열에 포함되지 않고 results
배열에 포함됩니다.
const Spy = vi.fn(() => ({ method: vi.fn() }));
const a = new Spy();
Spy.mock.instances[0] !== a;
Spy.mock.results[0] === a;