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

Proposal: partialMocked - mocked, but less strict return/resolved values. #1065

Closed
dylang opened this issue Apr 12, 2019 · 5 comments
Closed

Comments

@dylang
Copy link

dylang commented Apr 12, 2019

Issue :

I want to do something like this...

const mockFoo = mocked(foo);
mockFoo.mockReturnValue({
  valueNeededForTest: 'string' // TypeScript mad! foo returns other values too!
});

But because foo returns a dozen other properties that the test doesn't rely on, so we get errors like this:

Error:(21, 43) TS2345: Argument of type '{ valueNeededForTest: string }' is not assignable to parameter of type '{ buildPath: string; babelReactIntlPath:
string; cachePath: string; coveragePath: string; isCI: boolean; githubHostname: string; githubOrg: string; githubRepo: string; localPublicPath: string; ... 7 more ...; getPathWithoutRepoDirectory: 
(pathToShorten: string) => string; }'.
Type '{ valueNeededForTest: string; }' is missing the following properties from type '{ buildPath: string; babelReactIntlPath: string; cachePath: string; 
coveragePath: string; isCI: boolean; githubHostname: string; githubOrg: string; githubRepo: string; localPublicPath: string; ... 7 more ...; 
getPathWithoutRepoDirectory: (pathToShorten: string) => string; }': buildPath, babelReactIntlPath, cachePath, coveragePath, and 12 more.

Workarounds:

This takes away the nice typing mocked provides:

const mockFoo = mocked(foo);
mockFoo.mockReturnValue(({
  valueNeededForTest: 'string'
} as unknown) as ReturnType<foo>);

This isn't always possible, as running the original function can have side effects, or return something that can't be easily merged like a promise, and jest.requireActual's return type is any so it doesn't even solve the original problem.

const mockFoo = mocked(foo);
mockFoo.mockReturnValue({
  ...jest.requireActual('./foo'),
  valueNeededForTest: 'string'
});

Preferred behavior :

A new function called partialMocked (maybe there's a better name?) that allows returnType/resolvedValue/etc to be a deep partial of what it normally returns.

const mockFoo = partialMocked(foo);
mockFoo.mockReturnValue({
  valueNeededForTest: 'string' // TypeScript happy, developer happy!
});

Example implementation :

type DeepPartial<T> = {
    [P in keyof T]?: T[P] extends Array<infer U>
        ? Array<DeepPartial<U>>
        : T[P] extends ReadonlyArray<infer U>
            ? ReadonlyArray<DeepPartial<U>>
            : DeepPartial<T[P]>
};

type PartialReturnType<T extends MockableFunction> = 
    ReturnType<T> extends Promise<infer U>
        ? Promise<DeepPartial<U>>
        : ReturnType<T> extends Array<infer P>
            ? Array<DeepPartial<P>>
            : DeepPartial<ReturnType<T>>;

interface MockWithArgs<T extends MockableFunction> extends jest.MockInstance<PartialReturnType<T>, ArgumentsOf<T>> {
    new (...args: ConstructorArgumentsOf<T>): T;
    (...args: ArgumentsOf<T>): PartialReturnType<T>;
}

This fixed the issues I was having. I'm still fairly new with TypeScript, so I'm not sure if this is a complete solution or the right way to do it, so that's why I made this ticket instead of starting with a pull request.

Thoughts?

@ahnpnl
Copy link
Collaborator

ahnpnl commented Apr 16, 2019

there is a discussion about mock utils in #1048 . If jest team agrees to migrate mock utils to jest repo, perhaps this proposal can go into jest repo.

@ahnpnl
Copy link
Collaborator

ahnpnl commented Mar 18, 2020

Hi @dylang , I already mentioned this issue in jest feature request. I will close this issue as won’t build. If you still want to have this request, please create a request for jest team.

@brodyd795
Copy link

Did this partialMocked util proposal ever get moved over to a feature request in the jest repo? I see the PR for adding the mocked utils, but I can't seem to find anything for partialMocked.

@divmgl
Copy link

divmgl commented Mar 3, 2022

I'm also running into this issue in a codebase that I've inherited. The OP describes the problem very succinctly. The only workaround that the authors found was to stop using TypeScript with these kinds of files and use JSX instead.

@sbycrosz
Copy link

I have pasted this issue on jestjs/jest#13325. Hopefully, it will be picked up 🥲

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

No branches or pull requests

5 participants