Skip to content
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

Open
4 tasks done
segevfiner opened this issue Apr 3, 2024 · 3 comments
Open
4 tasks done

Add vi.createMockFromModule (Like jest.createMockFromModule) #5482

segevfiner opened this issue Apr 3, 2024 · 3 comments

Comments

@segevfiner
Copy link
Contributor

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:

import { jest } from '@jest/globals';

const mod = jest.createMockFromModule<typeof import('../foo')>('../foo');
mod.bar = jest.fn(() => 'qux');
export = mod;

But createMockFromModule is not available in Vitest, and importMock 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 like vi.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

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Apr 4, 2024

But createMockFromModule is not available in Vitest, and importMock is not the same, as when used inside a manual mock, it just ends up importing the manual mock itself cyclicly.

Is this maybe a bug? Or if it's causing some infinite loop, that needs to be fixed at least?

@segevfiner
Copy link
Contributor Author

Not an infinite loop, you are just getting your own module namespace object as far as I can tell. And I think importMock is supposed to import manual mocks so not a bug as far as I can tell.

@segevfiner segevfiner changed the title Add vi. createMockFromModule (Like jest.createMockFromModule) Add vi.createMockFromModule (Like jest.createMockFromModule) Apr 4, 2024
@hi-ogawa
Copy link
Contributor

hi-ogawa commented Apr 4, 2024

And I think importMock is supposed to import manual mocks so not a bug as far as I can tell.

It's called importMock, which sounds like an opposite of importActual https://vitest.dev/api/vi.html#vi-importactual but I thought the intent is simply "import actual + auto mocking" and could behave like Jest's createMockFromModule https://jestjs.io/docs/jest-object#jestcreatemockfrommodulemodulename.

public async importActual<T>(rawId: string, importer: string, callstack?: string[] | null): Promise<T> {
const { id, fsPath } = await this.resolvePath(rawId, importer)
const result = await this.executor.cachedRequest(id, fsPath, callstack || [importer])
return result as T
}
public async importMock(rawId: string, importee: string): Promise<any> {
const { id, fsPath, external } = await this.resolvePath(rawId, importee)
const normalizedId = this.normalizePath(fsPath)
let mock = this.getDependencyMock(normalizedId)
if (mock === undefined)
mock = this.resolveMockPath(fsPath, external)
if (mock === null) {
const mod = await this.executor.cachedRequest(id, fsPath, [importee])
return this.mockObject(mod)
}

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 vi.mock and overwrite some exports like this:

// 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');
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants