mirror of
https://github.com/vitest-dev/vitest.git
synced 2026-02-01 17:36:51 +00:00
docs: mocking documentation (#225)
This commit is contained in:
parent
8c1cdb87d9
commit
aa08ef4c7e
@ -95,6 +95,10 @@ export default defineConfig({
|
||||
text: 'Features',
|
||||
link: '/guide/features'
|
||||
},
|
||||
{
|
||||
text: 'Mocking',
|
||||
link: '/guide/mocking'
|
||||
},
|
||||
/* TODO
|
||||
{
|
||||
text: 'Using Plugins',
|
||||
|
||||
@ -160,7 +160,22 @@ You can also use `.skip`, `.only`, and `.todo` with concurrent suites and tests.
|
||||
|
||||
## Mocking
|
||||
|
||||
[Tinyspy](https://github.com/Aslemammad/tinyspy) built-in for mocking
|
||||
[Tinyspy](https://github.com/Aslemammad/tinyspy) built-in for mocking with `jest` compatible APIs on global `vi` object.
|
||||
|
||||
```ts
|
||||
const fn = vi.fn()
|
||||
|
||||
fn('hello', 1)
|
||||
|
||||
expect(vi.isMockFunction()).toBe(true)
|
||||
expect(fn.mock.calls[0]).toEqual(['hello', 1])
|
||||
|
||||
fn.mockImplementation((arg) => arg)
|
||||
|
||||
fn('world', 2)
|
||||
|
||||
expect(fn.mock.returns[0]).toBe('world')
|
||||
```
|
||||
|
||||
Vitest supports both [happy-dom](https://github.com/capricorn86/happy-dom) or [jsdom](https://github.com/jsdom/jsdom) for mocking DOM and browser APIs. They don't come with Vitest, you might need to install them:
|
||||
|
||||
|
||||
293
docs/guide/mocking.md
Normal file
293
docs/guide/mocking.md
Normal file
@ -0,0 +1,293 @@
|
||||
# Mocking
|
||||
|
||||
## Mocking functions
|
||||
|
||||
Mock functions (or "spies") observe functions, that are invoked in some other code, allowing you to test its arguments, output or even redeclare its implementation.
|
||||
|
||||
We use [Tinyspy](https://github.com/Aslemammad/tinyspy) as a base for mocking functions, but we have our own wrapper to make it `jest` compatible.
|
||||
|
||||
Both `vi.fn()` and `vi.spyOn()` share the same methods, but the return result of `vi.fn()` is callable.
|
||||
|
||||
### vi.fn
|
||||
|
||||
**Type:** `(fn: Function) => CallableMockInstance`
|
||||
|
||||
Creates a spy on a function, though can be initiated without one. Every time a function is invoked, it stores its call arguments, returns and instances. Also, you can manipulate its behavior with [methods](#mockmethods).
|
||||
If no function is given, mock will return `undefined`, when invoked.
|
||||
|
||||
```ts
|
||||
const getApples = vi.fn(() => 0)
|
||||
|
||||
getApples()
|
||||
|
||||
expect(getApples).toHaveBeenCalled()
|
||||
expect(getApples).toHaveReturnedWith(0)
|
||||
|
||||
getApples.mockReturnOnce(5)
|
||||
|
||||
const res = getApples()
|
||||
expect(res).toBe(5)
|
||||
expect(getApples).toHaveReturnedNthTimeWith(1, 5)
|
||||
```
|
||||
|
||||
### vi.spyOn
|
||||
|
||||
**Type:** `<T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance`
|
||||
|
||||
Creates a spy on a method or getter/setter of an object.
|
||||
|
||||
```ts
|
||||
let apples = 0
|
||||
const obj = {
|
||||
getApples: () => 13,
|
||||
}
|
||||
|
||||
const spy = vi.spyOn(obj, 'getApples').mockImplementation(() => apples)
|
||||
apples = 1
|
||||
|
||||
expect(obj.getApples()).toBe(1)
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
expect(spy).toHaveReturnedWith(1)
|
||||
```
|
||||
|
||||
## Mock methods
|
||||
|
||||
### mockName
|
||||
|
||||
**Type:** `(name: string) => MockInstance`
|
||||
|
||||
Sets internal mock name. Useful to see what mock has failed the assertion.
|
||||
|
||||
### getMockName
|
||||
|
||||
**Type:** `() => string`
|
||||
|
||||
Use it to return the name given to mock with method `.mockName(name)`.
|
||||
|
||||
### mockClear
|
||||
|
||||
**Type:** `() => MockInstance`
|
||||
|
||||
Clears all information about every call. After calling it, [`spy.mock.calls`](#mockcalls), [`spy.mock.returns`](#mockreturns) will return empty arrays. It is useful if you need to clean up spy between different assertions.
|
||||
|
||||
If you want this method to be called before each test automatically, you can enable [`clearMocks`](/config/#clearMocks) setting in config.
|
||||
|
||||
### mockReset
|
||||
|
||||
**Type:** `() => MockInstance`
|
||||
|
||||
Does what `mockClear` does and makes inner implementation as an empty function (returning `undefined`, when invoked). This is useful when you want to completely reset a mock back to its initial state.
|
||||
|
||||
If you want this method to be called before each test automatically, you can enable [`mockReset`](/config/#mockReset) setting in config.
|
||||
|
||||
### mockRestore
|
||||
|
||||
**Type:** `() => MockInstance`
|
||||
|
||||
Does what `mockRestore` does and restores inner implementation to the original function.
|
||||
|
||||
Note that restoring mock from `vi.fn()` will set implementation to an empty function that returns `undefined`. Restoring a `vi.fn(impl)` will restore implementation to `impl`.
|
||||
|
||||
If you want this method to be called before each test automatically, you can enable [`restoreMocks`](/config/#restoreMocks) setting in config.
|
||||
|
||||
### mockImplementation
|
||||
|
||||
**Type:** `(fn: Function) => MockInstance`
|
||||
|
||||
Accepts a function that will be used as an implementation of the mock.
|
||||
|
||||
For example:
|
||||
|
||||
```ts
|
||||
const mockFn = jest.fn().mockImplementation(apples => apples + 1);
|
||||
// or: jest.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
|
||||
|
||||
**Type:** `(fn: Function) => MockInstance`
|
||||
|
||||
Accepts a function that will be used as an implementation of the mock for one call to the mocked function. Can be chained so that multiple function calls produce different results.
|
||||
|
||||
```ts
|
||||
const myMockFn = jest
|
||||
.fn()
|
||||
.mockImplementationOnce(() => true)
|
||||
.mockImplementationOnce(() => false);
|
||||
|
||||
myMockFn(); // true
|
||||
myMockFn(); // false
|
||||
```
|
||||
|
||||
When the mocked function runs out of implementations, it will invok the default implementation that was set with `jest.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called:
|
||||
|
||||
```ts
|
||||
const myMockFn = jest
|
||||
.fn(() => 'default')
|
||||
.mockImplementationOnce(() => 'first call')
|
||||
.mockImplementationOnce(() => 'second call');
|
||||
|
||||
// 'first call', 'second call', 'default', 'default'
|
||||
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
|
||||
```
|
||||
|
||||
### mockReturnThis
|
||||
|
||||
**Type:** `() => MockInstance`
|
||||
|
||||
Sets inner implementation to return `this` context.
|
||||
|
||||
### mockReturnValue
|
||||
|
||||
**Type:** `(value: any) => MockInstance`
|
||||
|
||||
Accepts a value that will be returned whenever the mock function is called.
|
||||
|
||||
```ts
|
||||
const mock = jest.fn();
|
||||
mock.mockReturnValue(42);
|
||||
mock(); // 42
|
||||
mock.mockReturnValue(43);
|
||||
mock(); // 43
|
||||
```
|
||||
|
||||
### mockReturnValueOnce
|
||||
|
||||
**Type:** `(value: any) => MockInstance`
|
||||
|
||||
Accepts a value that will be returned whenever mock function is invoked. If chained, every consecutive call will return passed value. When there are no more `mockReturnValueOnce` values to use, calls a function specified by `mockImplementation` or other `mockReturn*` methods.
|
||||
|
||||
```ts
|
||||
const myMockFn = jest
|
||||
.fn()
|
||||
.mockReturnValue('default')
|
||||
.mockReturnValueOnce('first call')
|
||||
.mockReturnValueOnce('second call');
|
||||
|
||||
// 'first call', 'second call', 'default', 'default'
|
||||
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
|
||||
```
|
||||
|
||||
### mockResolvedValue
|
||||
|
||||
**Type:** `(value: any) => MockInstance`
|
||||
|
||||
Accepts a value that will be resolved, when async function will be called.
|
||||
|
||||
```ts
|
||||
test('async test', async () => {
|
||||
const asyncMock = jest.fn().mockResolvedValue(43);
|
||||
|
||||
await asyncMock(); // 43
|
||||
});
|
||||
```
|
||||
|
||||
### mockResolvedValueOnce
|
||||
|
||||
**Type:** `(value: any) => MockInstance`
|
||||
|
||||
Accepts a value that will be resolved for one call to the mock function. If chained, every consecutive call will resolve passed value.
|
||||
|
||||
```ts
|
||||
test('async test', async () => {
|
||||
const asyncMock = jest
|
||||
.fn()
|
||||
.mockResolvedValue('default')
|
||||
.mockResolvedValueOnce('first call')
|
||||
.mockResolvedValueOnce('second call');
|
||||
|
||||
await asyncMock(); // first call
|
||||
await asyncMock(); // second call
|
||||
await asyncMock(); // default
|
||||
await asyncMock(); // default
|
||||
});
|
||||
```
|
||||
|
||||
### mockRejectedValue
|
||||
|
||||
**Type:** `(value: any) => MockInstance`
|
||||
|
||||
Accepts an error that will be rejected, when async function will be called.
|
||||
|
||||
```ts
|
||||
test('async test', async () => {
|
||||
const asyncMock = jest.fn().mockRejectedValue(new Error('Async error'));
|
||||
|
||||
await asyncMock(); // throws "Async error"
|
||||
});
|
||||
```
|
||||
|
||||
### mockRejectedValueOnce
|
||||
|
||||
**Type:** `(value: any) => MockInstance`
|
||||
|
||||
Accepts a value that will be rejected for one call to the mock function. If chained, every consecutive call will reject passed value.
|
||||
|
||||
```ts
|
||||
test('async test', async () => {
|
||||
const asyncMock = jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce('first call')
|
||||
.mockRejectedValueOnce(new Error('Async error'));
|
||||
|
||||
await asyncMock(); // first call
|
||||
await asyncMock(); // throws "Async error"
|
||||
});
|
||||
```
|
||||
|
||||
## Mock properties
|
||||
|
||||
### mock.calls
|
||||
|
||||
This is an array containing all arguments for each call. One item of the array is arguments of that call.
|
||||
|
||||
If a function was invoked twice with the following arguments `fn(arg1, arg2)`, `fn(arg3, arg4)` in that order, then `mock.calls` will be:
|
||||
|
||||
```js
|
||||
[
|
||||
['arg1', 'arg2'],
|
||||
['arg3', 'arg4'],
|
||||
];
|
||||
```
|
||||
|
||||
### mock.results
|
||||
|
||||
This is an array containing all values, that were `returned` from function. One item of the array is an object with properties `type` and `value`. Available types are:
|
||||
|
||||
- `'return'` - function returned without throwing.
|
||||
- `'throw'` - function threw a value.
|
||||
|
||||
The `value` property contains returned value or thrown error.
|
||||
|
||||
If function returned `'result1`, then threw and error, then `mock.results` will be:
|
||||
|
||||
```js
|
||||
[
|
||||
{
|
||||
type: 'return',
|
||||
value: 'result',
|
||||
},
|
||||
{
|
||||
type: 'throw',
|
||||
value: Error,
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
### mock.instances
|
||||
|
||||
Currently, this property is not implemented.
|
||||
|
||||
## See also
|
||||
|
||||
- [Jest's Mock Functions](https://jestjs.io/docs/mock-function-api)
|
||||
Loading…
x
Reference in New Issue
Block a user