doMock cannot mock normally in sub-file import
Closed this issue · 6 comments
Describe the bug
Problem
doMock cannot mock normally in sub-file import
File structure
Please see test not working
part
src/index.ts
import userMsg from './user'
export function getUserMsg () {
return userMsg()
}
src/user/index.ts
export default function() {
return 'hello user'
}
test/index.spec.ts
import { describe, expect, it, vi } from 'vitest'
describe('test main', () => {
// normal work
it('getUserMsg mock success', async function() {
vi.doMock('@/user/index', async () => {
return {
default: function() {
return 'mock_success'
}
}
})
const { getUserMsg } = await import('@/index')
expect(getUserMsg()).toBe('mock_success')
vi.doUnmock('@/user/index')
})
// not working
it('getUserMsg mock fail', async function() {
vi.doMock('@/user/index', async () => {
return {
default: function() {
return 'mock_fail'
}
}
})
const { getUserMsg } = await import('@/index')
expect(getUserMsg()).toBe('mock_fail')
vi.doUnmock('@/user/index')
})
// not working
it('getUserMsg real', async function() {
const { getUserMsg } = await import('@/index')
expect(getUserMsg()).toBe('hello user')
})
})
when run pnpm run test
,show the following error
❯ test/index.spec.ts (3)
❯ test main (3)
✓ getUserMsg mock success
× getUserMsg mock fail
× getUserMsg real
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 2 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
FAIL test/index.spec.ts > test main > getUserMsg mock fail
AssertionError: expected 'mock_success' to be 'mock_fail' // Object.is equality
❯ test/index.spec.ts:29:26
27| })
28| const { getUserMsg } = await import('@/index')
29| expect(getUserMsg()).toBe('mock_fail')
| ^
30| vi.doUnmock('@/user/index')
31| })
- Expected "mock_fail"
+ Received "mock_success"
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯
FAIL test/index.spec.ts > test main > getUserMsg real
AssertionError: expected 'mock_success' to be 'hello user' // Object.is equality
❯ test/index.spec.ts:36:26
34| it('getUserMsg real', async function() {
35| const { getUserMsg } = await import('@/index')
36| expect(getUserMsg()).toBe('hello user')
| ^
37| })
38| })
- Expected "hello user"
+ Received "mock_success"
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/2]⎯
Test Files 1 failed (1)
Tests 2 failed | 1 passed (3)
Start at 23:22:18
Duration 463ms (transform 77ms, setup 0ms, collect 45ms, tests 20ms)
### Reproduction
https://github.com/GreenMashimaro/bug-reproduce-vitest-domock
### System Info
```shell
System:
OS: macOS 12.2.1
CPU: (8) x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
Memory: 27.91 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.11.0 - ~/.nvm/versions/node/v16.11.0/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v16.11.0/bin/yarn
npm: 8.0.0 - ~/.nvm/versions/node/v16.11.0/bin/npm
Browsers:
Chrome: 111.0.5563.110
Edge: 111.0.1661.44
Safari: 15.3
npmPackages:
@vitest/coverage-c8: ^0.29.7 => 0.29.7
@vitest/ui: ^0.29.7 => 0.29.7
vitest: ^0.29.7 => 0.29.7
Used Package Manager
pnpm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
Your first top level import is already evaluated with its dependencies, you cannot mock dependencies after the module is imported.
@sheremet-va Thank you for your reply. I re-updated the example, each test dynamic imports @/index
, but only one doMock works fine. The other two test failed. Looks like a bug.
Because there is such a scenario, it is necessary to simulate the different return values of a certain method, but this method may be in a relatively low-level file.
New examples don't change much. @/index
is evaluated only once as per ESM spec. You need to reset modules cache (vi.resetModules
), if you rely on a mocked file inside another module.
@sheremet-va Thank you very much for your patience. There is still a problem. I updated the file again. But vi.resetAllMocks()
has no effect.
The updated file content is as follows:
index.spec.ts
import { describe, expect, it, vi } from 'vitest'
describe('test main', () => {
// normal work
it('getUserMsg mock success', async function() {
vi.resetAllMocks()
vi.doMock('@/user/index', async () => {
return {
default: function() {
return 'mock_success'
}
}
})
const { getUserMsg } = await import('@/index')
expect(getUserMsg()).toBe('mock_success')
vi.doUnmock('@/user/index')
})
// not working
it('getUserMsg mock fail', async function() {
vi.resetAllMocks()
vi.doMock('@/user/index', async () => {
return {
default: function() {
return 'mock_fail'
}
}
})
const { getUserMsg } = await import('@/index')
expect(getUserMsg()).toBe('mock_fail')
vi.doUnmock('@/user/index')
})
// not working
it('getUserMsg real', async function() {
vi.resetAllMocks()
const { getUserMsg } = await import('@/index')
expect(getUserMsg()).toBe('hello user')
})
})
The minimal reproducible example:https://github.com/GreenMashimaro/bug-reproduce-vitest-domock/tree/main
vi.resetAllMocks
is not vi.resetModules
I apologize for my carelessness. Now the test passes perfectly. Thank you very much for your answer.