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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for jest.mock to assist in typescript environments #10948

Closed
Paratron opened this issue Dec 13, 2020 · 6 comments
Closed

Proposal for jest.mock to assist in typescript environments #10948

Paratron opened this issue Dec 13, 2020 · 6 comments

Comments

@Paratron
Copy link

Paratron commented Dec 13, 2020

馃殌 Feature Proposal

It would be super helpful if jest.mock could return the module (maybe with updated typings).

Motivation

Right now, when writing unit tests with jest and typescript, mocking modules becomes boilerplatey. This is because the IDE does not understand that after calling jest.mock("myModule") all exported functions of that module are of type jest.Mock. Therefore, when I try to call methods like myModule.mockReturnValue() or the likes, the IDE / typescript complains that this is nonsense - those functions do not exist on the module/function.

In order to get correct typings, one has to import a mocked module like this:

jest.mock("node-fetch");
import {default as fetchOriginal} from "node-fetch";

const fetch = fetchOriginal as unknown as jest.Mock;

Example

My idea is to let jest.mock return an instance of the mocked module - in the best case with correct typings. So the whole boilerplate could be reduced to:

const fetch = jest.mock("node-fetch");

Even if its not possible to add the correct typings directly in jest, it would make re-assigning mock types much easier:

const fetch = jest.mock("node-fetch") as unknown as jest.Mock;

Or when importing just some features of a module:

const {a, b} = jest.mock("myModule") as unknown as {a: jest.Mock, b: jest.Mock};

Thats possibly a problem since I saw that jest.mock currently returns an instance of jest for method chaining. So changing the behaviour would possibly break some peoples unit tests. Adding a property to the config argument could change that or maybe introducing a completely new method that combines mock + require.

@ahnpnl
Copy link
Contributor

ahnpnl commented Dec 13, 2020

@SimenB
Copy link
Member

SimenB commented Dec 14, 2020

We cannot change jest.mock to have any return-value but the current jest (for chaining) as it's hoisted by the babel plugin.

Also, jest.mock today doesn't actually mock the module right away, it just registers the fact that this module will be mocked whenever it is required.

Thirdly, there is no way in TypeScript to infer shape of an import except via typeof import('blahblah') (with a string literal) - so we'd either need to accept a generic or you will need to keep casting.

All that is to say there'd still be some boilerplate and we'd need a new API in order to implement this. Not blockers of course, but a significant effort.


The mocked helper @ahnpnl links solves half your issue I think (getting correct types), but still quite boilerplatey. I'm not sure if it's worth introducing an entire new API in order to reduce 3 lines into 1, tho... You can do something like

const fetch = mockAndRequire<typeof import('node-fetch')>('node-fetch');

function mockAndRequire<T = unknown>(moduleToImport: string): T {
  jest.mock(moduleToImport)

  const importedModule = require(moduleToImport);

  return mocked(importedModule, true)
}

or for ESM (though blocked on #10025 for now)

const fetch = await mockAndImport<typeof import('node-fetch')>('node-fetch');

async function mockAndImport<T = unknown>(moduleToImport: string): Promise<T> {
  jest.mockModule(moduleToImport)

  const importedModule = await import(moduleToImport);

  return mocked(importedModule, true)
}

Still some boilerplate (you have to say 'node-fetch' twice), but I don't think that's avoidable.

@wh1t3cAt1k
Copy link

I am successfully using https://github.com/userlike/joke for "mock and import" behaviour. In a recent version, they actually use the "mocked" helper mentioned above for typings, so far, I have not encountered any problems with the types whatsoever.

@github-actions
Copy link

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 14 days.

@github-actions github-actions bot added the Stale label Feb 25, 2022
@github-actions
Copy link

This issue was closed because it has been stalled for 7 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.

@github-actions
Copy link

github-actions bot commented May 6, 2022

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants