jestjs - Hur man på rätt sätt mockar en överbelastad Typescript-funktion med Jest


Jag försöker mocka en enskild funktion på en instans med Typescript och Jest. Instansen är en OAuth2Client från Googles Auth Library. Här är min modul som testas:

sample.ts

import {OAuth2Client } from "google-auth-library";

export async function accessToken(): Promise<string | undefined> {
    const client: OAuth2Client = new OAuth2Client(
        "clientId", "clientSecret", "https://redirect.com"
    );
    const response = await client.getToken("code");
    return response?.tokens.access_token;
}

För testet skulle jag vilja returnera ett fast svar från getToken-anropet. Det som gör detta lite mer komplicerat är att getToken är överlagrat och att google-auth-library är TypeScript.

getToken(code: string): Promise<GetTokenResponse>;
getToken(options: GetTokenOptions): Promise<GetTokenResponse>;
getToken(code: string, callback: GetTokenCallback): void;
getToken(options: GetTokenOptions, callback: GetTokenCallback): void;

Det här är mitt test:

sample.test.ts

import { OAuth2Client } from 'google-auth-library';
import {accessToken} from "./sample";
import {GetTokenResponse} from "google-auth-library/build/src/auth/oauth2client";

type GetTokenByCode = (code: string) => Promise<GetTokenResponse>

const oAuth2Client = jest.spyOn(OAuth2Client.prototype, 'getToken') as unknown as jest.MockedFunction<GetTokenByCode>;
oAuth2Client.mockImplementation((code: string) => {
    if (code != "code") return Promise.reject("Unexpected code.");

    const response = {
        tokens: {
            refresh_token: `abc${code}`,
            access_token: "def"
        },
        res: null
    }
    return Promise.resolve(response);
});


describe('Sample', function () {
    beforeEach(() => {
        jest.resetModules();
        jest.restoreAllMocks();
    });

    it('can get a token', async () => {
        const token = await accessToken();
        expect(token).toBeDefined();
        expect(oAuth2Client).toHaveBeenCalled();
    });
});

När jag kör detta test får jag följande fel - vilket tyder på att klienten försöker det verkliga anropet.

Error: invalid_client

    at Gaxios._request (/Users/foo/dev/token-service/node_modules/gaxios/src/gaxios.ts:158:15)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at OAuth2Client.getTokenAsync (/Users/foo/dev/token-service/node_modules/google-auth-library/build/src/auth/oauth2client.js:124:21)
    at Object.accessToken (/Users/foo/dev/token-service/src/functions/sample.ts:7:22)
    at Object.<anonymous> (/Users/foo/dev/token-service/src/functions/sample.test.ts:29:23)

Om man tittar på filen .. google-auth-library/build/src/auth/oauth2client.js verkar det som att TS-transpilern genererade en js-funktion med signaturen getToken(codeOrOptions, callback) - som sedan kallar getTokenAsync.

Jag är lite vilse här, mockar jag fel överlagring med jest.spy?