Skip to content

Commit fd8292a

Browse files
authoredDec 2, 2022
fix(mocker): set cache before mocking to allow circular dependencies (#2391)
1 parent a6a94cc commit fd8292a

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed
 

‎packages/vitest/src/runtime/mocker.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { existsSync, readdirSync } from 'fs'
22
import { isNodeBuiltin } from 'mlly'
33
import { basename, dirname, extname, join, resolve } from 'pathe'
4-
import { normalizeRequestId, pathFromRoot, toFilePath } from 'vite-node/utils'
4+
import { normalizeRequestId, pathFromRoot } from 'vite-node/utils'
55
import type { ModuleCacheMap } from 'vite-node/client'
66
import { getAllMockableProperties, getType, getWorkerState, mergeSlashes, slash } from '../utils'
77
import { distDir } from '../constants'
@@ -195,7 +195,7 @@ export class VitestMocker {
195195
return existsSync(fullPath) ? fullPath : null
196196
}
197197

198-
public mockObject(object: Record<string | symbol, any>) {
198+
public mockObject(object: Record<Key, any>, mockExports: Record<Key, any> = {}) {
199199
if (!VitestMocker.spyModule) {
200200
throw new Error(
201201
'Error: Spy module is not defined. '
@@ -275,7 +275,7 @@ export class VitestMocker {
275275
}
276276
}
277277

278-
const mockedObject: Record<Key, any> = {}
278+
const mockedObject: Record<Key, any> = mockExports
279279
mockPropertiesOf(object, mockedObject)
280280

281281
// Plug together refs
@@ -360,10 +360,12 @@ export class VitestMocker {
360360
const cache = this.moduleCache.get(mockPath)
361361
if (cache?.exports)
362362
return cache.exports
363-
const cacheKey = toFilePath(dep, this.root)
364-
const mod = this.moduleCache.get(cacheKey)?.exports || await this.request(dep)
365-
const exports = this.mockObject(mod)
363+
364+
const exports = {}
365+
// Assign the empty exports object early to allow for cycles to work. The object will be filled by mockObject()
366366
this.moduleCache.set(mockPath, { exports })
367+
const mod = await this.request(dep)
368+
this.mockObject(mod, exports)
367369
return exports
368370
}
369371
if (typeof mock === 'function' && !callstack.includes(mockPath)) {
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { expect, it, vi } from 'vitest'
2+
// The order of the two imports here matters: B before A
3+
import { circularB } from '../src/circularB'
4+
import { circularA } from '../src/circularA'
5+
6+
vi.mock('../src/circularB')
7+
8+
it('circular', () => {
9+
circularA()
10+
11+
expect(circularB).toHaveBeenCalledOnce()
12+
})

0 commit comments

Comments
 (0)
Please sign in to comment.