-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add vi.createMockFromModule
(Like jest.createMockFromModule
)
#5482
Comments
Is this maybe a bug? Or if it's causing some infinite loop, that needs to be fixed at least? |
Not an infinite loop, you are just getting your own module namespace object as far as I can tell. And I think |
vi. createMockFromModule
(Like jest.createMockFromModule
)vi.createMockFromModule
(Like jest.createMockFromModule
)
It's called vitest/packages/vitest/src/runtime/mocker.ts Lines 437 to 455 in e4e939b
Btw, can you setup a small reproduction to illustrate what you want to do with a concrete code? That would be helpful anyway as a test case if it's implemented. Also it would also help for us to suggest a workaround with what's currently possible. One idea just came to my mind is to still use // use `setupFiles` to setup mock for all test files
import { vi, beforeEach } from "vitest"
import * as fooLib from "./foo";
// setup auto mocking for a whole module
vi.mock("./foo");
beforeEach(() => {
// then customize some named export
vi.mocked(fooLib).bar.mockImplementation(() => 'qux');
}); |
@hi-ogawa Here is an attempt to show what I'm trying to do, though a bit of a contrived example, I hope it shows what I'm trying to do: https://github.com/segevfiner/vitest-partial-manual-mock |
I don't think we can support any dynamic imports for this use case because ESM needs to know every named import during parsing, but maybe we can support something like this: // __mocks__/foo.js
export * from '../foo.js' with { mock: 'auto' }
export const bar = vi.fn(() => 'qux') |
AFAIK you can do dynamic imports in ESM, aka |
Yes, this is what I meant. The JS engine cannot parse the file to see all exported variables if you use a dynamic import because there is no mechanism to dynamically export variables.
This only works in Node.js runner because Vitest supports loading source code as CJS, this will not work in the browser (and module mocking is supported in the browser mode in the latest beta). This will also not work in future versions of Vitest because we cannot process files that were imported using
Also, |
To achieve the desired behavior, I used // __mocks__/foo.js
vi.mock('../foo.js', async (importOriginal) => ({
...(await importOriginal()),
bar: vi.fn(() => 'qux')
})); In the test file, I included: vi.mock('./foo.js'); Initially, I wasn’t certain this logic would work, given that |
Last time I tried, I got an infinite loop from |
For me, with the latest version (2.1.4), it worked |
There was a related discussion with a similar use case #7548 and now I found that there might be an vi.mock(import("./foo"), async (importOriginal) => {
const original = await importOriginal();
// use automocking utility provided by @vitest/mocker
const { vi } = await import("vitest");
const { mockObject } = await import("@vitest/mocker");
const mocked = mockObject(
{
type: "automock",
spyOn: vi.spyOn,
globalConstructors: {
Object,
Function,
RegExp,
Array,
Map,
},
},
original,
);
return {
...mocked, // mock all exports
addOne: original.addOne, // expect this one
};
}); Perhaps we can support this |
For OP's case #5482 (comment), Example: __mocks__/foo.ts// __mocks__/foo.ts
import { vi } from 'vitest';
import { mockObject } from '@vitest/mocker';
const original = await vi.importActual('../foo');
const mocked = mockObject(
{
type: "automock",
spyOn: vi.spyOn,
globalConstructors: {
Object,
Function,
RegExp,
Array,
Map,
},
},
original,
);
export const foo = mocked.foo;
export const bar = mocked.bar;
export const hello = vi.fn(() => 'TEST'); |
Clear and concise description of the problem
I want to create a manual mock (
__mocks__
), but only specialize parts of the default mock that is automatically created by vitest, in Jest I could do:But
createMockFromModule
is not available in Vitest, andimportMock
is not the same, as when used inside a manual mock, it just ends up importing the manual mock itself cyclicly.createMockFromModule
always returns the automatically created mock object even if there is a manual mock.Suggested solution
Add
vi.createMockFromModule
or under a different name that better fits it's async nature in vitest, that acts likevi.importMock
but always return an automatically created mock even if there is a manual mock.Alternative
Manually mock everything in the manual mock, which is cumbersome and harder to maintain.
Additional context
Encountered while migrating some tests from Jest to Vitest due to Jest's ESM issues.
#3718
Validations
The text was updated successfully, but these errors were encountered: