Closed rstainsby closed 1 month ago
Hey @rstainsby! 👋 I'm here to help you with any bugs, questions, or contributions you might have. I'm a bot that can assist with all things related to software development.
To address the issue where mockRestore
restores a mocked function to undefined, you can define an initial value for the mocked function. Here is an updated version of the documentation example:
const { useStorageMock } = vi.hoisted(() => {
return {
useStorageMock: vi.fn(() => {
return { value: 'mocked storage' }
})
}
})
mockNuxtImport('useStorage', () => {
return useStorageMock
})
// Then, inside a test
useStorageMock.mockImplementation(() => {
return { value: 'something else' }
})
This approach ensures that the mocked function has a defined initial value, avoiding the issue where mockRestore
restores it to undefined. This solution aligns with the behavior described in the Vitest documentation [1].
To continue talking to Dosu, mention @dosu.
Feel free to dismiss this if you feel this is expected behavior. It's just that, for me, the docs imply that the initial hoisted mock value would be the restore state.
To clarify the behavior and avoid confusion, the Nuxt testing documentation can be updated to explicitly state that the initial hoisted mock value is not the restore state unless explicitly defined. Here is a suggested update to the documentation:
## Mocking in Nuxt Tests
When using the `mockNuxtImport` and `mockComponent` helpers, it's important to understand how the hoisted mock values are managed. By default, the initial hoisted mock value is not considered the restore state. This means that calling `mockRestore` will set all hoisted mocks to `undefined` unless you explicitly define the restore state.
### Example
```js
import { vi } from 'vitest';
import { mockNuxtImport, mockComponent } from 'nuxt-vitest-mocks';
vi.hoisted(() => {
if (!globalThis.__NUXT_VITEST_MOCKS) {
vi.stubGlobal('__NUXT_VITEST_MOCKS', {});
}
});
// Define your mocks
mockNuxtImport('someModule', () => ({ someFunction: vi.fn(() => 'initial value') }));
mockComponent('SomeComponent', () => ({ default: vi.fn(() => 'initial value') }));
// Restore mocks
vi.mockRestore(); // This will set all hoisted mocks to `undefined` unless explicitly defined
To avoid issues with mockRestore
, ensure that you define the restore state explicitly if needed.
This update clarifies the behavior and helps users avoid potential issues with undefined mocks when using `mockRestore` <sup>[[1]](https://github.com/nuxt/test-utils/blob/main/src/module/plugins/mock.ts)</sup>.
<!-- Dosu Comment Footer -->
*To continue talking to [Dosu](https://dosu.dev), mention @dosu.*
Environment
Reproduction
https://stackblitz.com/edit/github-htfm4n?file=README.md
Describe the bug
Nuxt's testing documentation recommends restoring mocks that you have hoisted using vi.hoisted() https://nuxt.com/docs/getting-started/testing#built-in-mocks.
The approach the documentation recommends for this is:
but when using vitests mock restore, this results in useStorageMock being immediately restored to undefined. So, unless you mock useStorageMock in every test, it will likely cause broken tests. This doesn't feel like the implied behavior - In the example above I expected restoring the mock to reset 'value' to 'mocked storage'.
This happens because mockRestore will restore a mocked function (
vi.fn()
) to undefined if that mocked function doesn't have an initial value (vi.fn(initalval)
). Docs on that are here: https://vitest.dev/api/mock.html#mockrestore.The solution for this then seems to be to define a initial value for the mocked function. So I propose that the docs are changed to:
I've included a stackblitz with tests that showcase this. More detail is included in the README of the stackblitz.
Additional context
TLDR: If you follow the docs recommendation of calling mockRestore before each test, you will end up with undefined mocks for every mocked Nuxt import that requires different implementations between tests.
Logs
No response