You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This assertion checks that every behavior registered on a [`vi.when`](/api/vi#vi-when) chain has been consumed. A behavior is considered exhausted when it has been called the number of times specified by its `times` option, or at least once for behaviors that apply indefinitely.
1461
+
1462
+
Requires a `When` chain returned by `vi.when` to be passed to `expect`.
1463
+
1464
+
```ts
1465
+
import { expect, test, vi } from'vitest'
1466
+
1467
+
test('all behaviors were consumed', () => {
1468
+
const spy =vi.fn()
1469
+
const w =vi.when(spy)
1470
+
.calledWith(1)
1471
+
.thenReturnOnce('once')
1472
+
.calledWith(2)
1473
+
.thenReturn('always')
1474
+
1475
+
expect(w).not.toHaveBeenExhausted()
1476
+
1477
+
spy(1) // consumes the `thenReturnOnce` behavior
1478
+
spy(2) // satisfies the `thenReturn` behavior (called at least once)
1479
+
1480
+
expect(w).toHaveBeenExhausted()
1481
+
})
1482
+
```
1483
+
1484
+
::: warning
1485
+
A `When` chain with no registered behaviors is never considered exhausted. `toHaveBeenExhausted` only passes when at least one `calledWith` with an associated action (`then*`) has been registered and every registered behavior has been fully consumed.
function when(spy:Mock, options?:WhenOptions):When
812
+
```
813
+
814
+
Defines per-argument behaviors on a spy, replacing its implementation for the duration of the `when` chain.
815
+
816
+
Call `.calledWith(...args)` on the returned object to specify which call arguments to match, then chain one or more `then*` methods to declare what the spy should return, throw, or resolve when invoked with those arguments. Arguments are matched with deep equality and support asymmetric matchers such as `expect.any()`.
| `thenThrowOnce(error)` | Throws `error` once, then falls back. |
839
+
| `thenResolve(value, options?)` | Returns a resolved `Promise` with `value`. |
840
+
| `thenResolveOnce(value)` | Resolves once, then falls back. |
841
+
| `thenReject(error, options?)` | Returns a rejected `Promise` with `error`. |
842
+
| `thenRejectOnce(error)` | Rejects once, then falls back. |
843
+
844
+
The optional `times` option limits how many times a behavior applies before being exhausted. Behaviors registered for the same arguments are consumed last-in-first-out: the most recently registered behavior is tried first, and once exhausted, earlier ones act as fallbacks.
.thenReturn('dark', { times: 2 }) // applied first for the next 2 calls
853
+
854
+
expect(spy('theme')).toBe('dark')
855
+
expect(spy('theme')).toBe('dark')
856
+
expect(spy('theme')).toBe('light') // falls back
857
+
```
858
+
859
+
When called with arguments that match no registered behavior, the spy falls through to its original implementation by default. Use the `onUnmatched` option to change this:
860
+
861
+
- `'passthrough'` (**default**):delegatestothespy's original implementation
862
+
- `'throw'`: throws an error listing the unmatched arguments
863
+
- a function: called with the unmatched arguments; itsreturnvalueisused
864
+
865
+
```ts
866
+
const spy = vi.fn<(id: number) => string>()
867
+
868
+
vi.when(spy, { onUnmatched: 'throw' })
869
+
.calledWith(1)
870
+
.thenReturn('Alice')
871
+
872
+
expect(spy(1)).toBe('Alice')
873
+
expect(() => spy(99)).toThrow() // no behavior defined for 99
spy(2) // satisfies `thenReturn` (called at least once)
890
+
891
+
expect(w).toHaveBeenExhausted()
892
+
```
893
+
894
+
::: tip
895
+
Inenvironmentsthatsupport [ExplicitResourceManagement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Resource_management), you can use `using` instead of `const` to automatically restore the spy's original implementation when the containing block exits:
896
+
897
+
```ts
898
+
const spy = vi.fn(() => 'original')
899
+
900
+
{
901
+
using w = vi.when(spy)
902
+
.calledWith('hello')
903
+
.thenReturn('mocked')
904
+
905
+
expect(spy('hello')).toBe('mocked')
906
+
} // ← spy's original implementation is restored here
`mockReturnValue` always returns the same value regardless of the arguments the mock receives. If you need argument-specific return values, [`vi.when`](/api/vi#vi-when) lets you attach different behaviors for different argument combinations without writing your own `if/else` logic. See the [Conditional Mocking](/guide/recipes/conditional-mocking) recipe for details.
77
+
:::
78
+
75
79
## Mock Implementation
76
80
77
81
Sometimes you need more than a fixed return value. You want the mock to actually do something with its arguments. [`mockImplementation`](/api/mock#mockimplementation) lets you provide a full replacement function:
Copy file name to clipboardExpand all lines: docs/guide/mocking/functions.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,10 @@ If you need to pass down a custom function implementation as an argument or crea
8
8
9
9
Both `vi.spyOn` and `vi.fn` share the same methods.
10
10
11
+
::: tip
12
+
If you need a mock to return different values depending on the arguments it receives, [`vi.when()`](/api/vi#vi-when) lets you define argument-specific behaviors without writing your own `if/else` logic. See the [Conditional Mocking](/guide/recipes/conditional-mocking) recipe for details.
0 commit comments