I am trying to mock a single function on an instance using Typescript and Jest. Then instance is an OAuth2Client
from Google's Auth Library. Here is my module under test:
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;
}
For the test, I'd like to return a fixed response from the getToken
call. What makes this a bit more complicated, is that getToken
is overloaded and that the google-auth-library
is Typescript.
getToken(code: string): Promise<GetTokenResponse>;
getToken(options: GetTokenOptions): Promise<GetTokenResponse>;
getToken(code: string, callback: GetTokenCallback): void;
getToken(options: GetTokenOptions, callback: GetTokenCallback): void;
This is my 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();
});
});
When I run this test, I receive the following error - which indicates that the client is trying the real call.
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)
Looking at the file .. google-auth-library/build/src/auth/oauth2client.js
, it seems that the TS transpiler output a js-function with signature getToken(codeOrOptions, callback)
- which then calls getTokenAsync
.
I am a bit lost here, am I mocking the wrong overload with jest.spy
?
I believe the problem is this:
const client: OAuth2Client = new OAuth2Client(
"clientId", "clientSecret", "https://redirect.com"
);
While what you are actually trying to mock is the prototype
parent object.
const oAuth2Client = jest.spyOn(OAuth2Client.prototype, 'getToken') as unknown as jest.MockedFunction<GetTokenByCode>;
I would try the following:
prototype
off the mock
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.