Skip to content

Commit 465bdb3

Browse files
feat: add vi.mockObject to automock any object (#7761)
Co-authored-by: Vladimir <sleuths.slews0s@icloud.com>
1 parent 4af5df3 commit 465bdb3

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

docs/api/vi.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,33 @@ expect(res).toBe(5)
390390
expect(getApples).toHaveNthReturnedWith(2, 5)
391391
```
392392

393+
### vi.mockObject <Version>3.2.0</Version>
394+
395+
- **Type:** `<T>(value: T) => MaybeMockedDeep<T>`
396+
397+
Deeply mocks properties and methods of a given object in the same way as `vi.mock()` mocks module exports. See [automocking](/guide/mocking.html#automocking-algorithm) for the detail.
398+
399+
```ts
400+
const original = {
401+
simple: () => 'value',
402+
nested: {
403+
method: () => 'real'
404+
},
405+
prop: 'foo',
406+
}
407+
408+
const mocked = vi.mockObject(original)
409+
expect(mocked.simple()).toBe(undefined)
410+
expect(mocked.nested.method()).toBe(undefined)
411+
expect(mocked.prop).toBe('foo')
412+
413+
mocked.simple.mockReturnValue('mocked')
414+
mocked.nested.method.mockReturnValue('mocked nested')
415+
416+
expect(mocked.simple()).toBe('mocked')
417+
expect(mocked.nested.method()).toBe('mocked nested')
418+
```
419+
393420
### vi.isMockFunction
394421

395422
- **Type:** `(fn: Function) => boolean`

packages/vitest/src/integrations/vi.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,37 @@ export interface VitestUtils {
268268
path: string
269269
) => Promise<MaybeMockedDeep<T>>
270270

271+
/**
272+
* Deeply mocks properties and methods of a given object
273+
* in the same way as `vi.mock()` mocks module exports.
274+
*
275+
* @example
276+
* ```ts
277+
* const original = {
278+
* simple: () => 'value',
279+
* nested: {
280+
* method: () => 'real'
281+
* },
282+
* prop: 'foo',
283+
* }
284+
*
285+
* const mocked = vi.mockObject(original)
286+
* expect(mocked.simple()).toBe(undefined)
287+
* expect(mocked.nested.method()).toBe(undefined)
288+
* expect(mocked.prop).toBe('foo')
289+
*
290+
* mocked.simple.mockReturnValue('mocked')
291+
* mocked.nested.method.mockReturnValue('mocked nested')
292+
*
293+
* expect(mocked.simple()).toBe('mocked')
294+
* expect(mocked.nested.method()).toBe('mocked nested')
295+
* ```
296+
*
297+
* @param value - The object to be mocked
298+
* @returns A deeply mocked version of the input object
299+
*/
300+
mockObject: <T>(value: T) => MaybeMockedDeep<T>
301+
271302
/**
272303
* Type helper for TypeScript. Just returns the object that was passed.
273304
*
@@ -606,6 +637,10 @@ function createVitest(): VitestUtils {
606637
return _mocker().importMock(path, getImporter('importMock'))
607638
},
608639

640+
mockObject<T>(value: T) {
641+
return _mocker().mockObject({ value }).value
642+
},
643+
609644
// this is typed in the interface so it's not necessary to type it here
610645
mocked<T>(item: T, _options = {}): any {
611646
return item

test/core/test/vi.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,38 @@ describe('testing vi utils', () => {
200200
expect(mod).toBeDefined()
201201
expect(mod.timeout).toBe(100)
202202
})
203+
204+
test('mockObject', () => {
205+
const original = {
206+
simple: () => 'value',
207+
nested: {
208+
method: () => 'real',
209+
},
210+
prop: 'foo',
211+
}
212+
213+
const mocked = vi.mockObject(original)
214+
expect(mocked.simple()).toBe(undefined)
215+
expect(mocked.nested.method()).toBe(undefined)
216+
expect(mocked.prop).toBe('foo')
217+
mocked.simple.mockReturnValue('mocked')
218+
mocked.nested.method.mockReturnValue('mocked nested')
219+
expect(mocked.simple()).toBe('mocked')
220+
expect(mocked.nested.method()).toBe('mocked nested')
221+
222+
class OriginalClass {
223+
constructor() {
224+
throw new Error('should be mocked!')
225+
}
226+
227+
someFn() {
228+
return 'value'
229+
}
230+
}
231+
const MockedClass = vi.mockObject(OriginalClass)
232+
const mockedInstance = new MockedClass()
233+
expect(MockedClass).toHaveBeenCalled()
234+
vi.mocked(mockedInstance).someFn.mockImplementation(() => 'mocked')
235+
expect(mockedInstance.someFn()).toBe('mocked')
236+
})
203237
})

0 commit comments

Comments
 (0)