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

Expect mock factories to have a return type compatible with the original module #6089

Closed
4 tasks done
acidoxee opened this issue Jul 11, 2024 · 0 comments · Fixed by #6139
Closed
4 tasks done

Expect mock factories to have a return type compatible with the original module #6089

acidoxee opened this issue Jul 11, 2024 · 0 comments · Fixed by #6139
Labels
p2-nice-to-have Not breaking anything but nice to have (priority) pr welcome

Comments

@acidoxee
Copy link

Clear and concise description of the problem

Currently, when using mock factories, the expected return type is any. This makes it possible to return broken mocks that do not comply with the original module's signature.

// @filename: src/basic.ts
export const squared = (n: number) => n * n

// @filename: test/mocks.test.ts
import { expect, test, vi } from 'vitest';

test('Mocked module with broken contract', async () => {
  vi.doMock(import('../src/basic.js'), () => ({
    // When not manually typing the result, we can return a broken mock from the factory, as its expected return type is `any`
    sqrd: () => 1,
  }));

  // This throws the following error: Error: [vitest] No "squared" export is defined on the "../src/basic.js" mock. Did you forget to return it from "vi.mock"?
  const { squared } = await import('../src/basic.js');
  expect(squared(2)).toBe(1);
});

Suggested solution

It would be great if the mock factory's return type was expected to be the same as the original module's, instead of using any.

Alternative

Meanwhile, we've got hundreds of return type overrides in our codebase for each mock with satisfies Awaited<ReturnType<typeof importOriginal>> to ensure the mock's type is correct, but this is tedious and error-prone.

// @filename: src/basic.ts
export const squared = (n: number) => n * n

// @filename: test/mocks.test.ts
import { expect, test, vi } from 'vitest';

test('Mocked module', async () => {
  vi.doMock(
    import('../src/basic.js'),
    (importOriginal) =>
      // This ensures the value returned from the factory is compatible with the original module.
      // I would like for the whole `satisfies` statement to not be necessary
      ({ squared: () => 1 } satisfies Awaited<
        ReturnType<typeof importOriginal>
      >)
  );

  const { squared } = await import('../src/basic.js');
  expect(squared(2)).toBe(1);
});

Additional context

Here's a reproduction: https://stackblitz.com/edit/vitest-dev-vitest-fkhseh?file=test%2Fmocks.test.ts

Validations

@sheremet-va sheremet-va added pr welcome p2-nice-to-have Not breaking anything but nice to have (priority) and removed enhancement: pending triage labels Jul 11, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Aug 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
p2-nice-to-have Not breaking anything but nice to have (priority) pr welcome
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants