Short Answer
The global spyOn(...) function returns a jasmine.Spy not a jest.SpyInstance. The reason for this, as far as I can tell, is to ease migration from Jasmine to Jest.
Here are two options:
let barSpy: jest.SpyInstance;
barSpy = jest.spyOn(a, 'bar'); // <--- explicitly use jest.spyOn
// or
let barSpy: jasmine.Spy; // <--- use jasmine.Spy as your type
barSpy = spyOn(a, 'bar');
Further Explanation
The node_modules\@types\jest\index.d.ts file has the Jest type definitions. By looking at them, we can see the two implementations of spyOn.
- The
spyOnthat returns ajest.SpyInstanceis inside thejestnamespace. - The
spyOnthat returns ajasmine.Spyis in the global namespace.
Unless you're in the process of migrating from Jasmine to Jest, I would use the jest.spyOn function instead of the global one.
jestjs - Jest spyOn not working with typescript: "Property 'mockRestore' is missing in type 'Spy'" - Stack Overflow
jestjs - TypeScript+Jest - how to use jest.spyOn with generic TypeScript methods? - Stack Overflow
[deleted by user]
jest.spyOn does not work when compared ts-jest
I think all you're missing is the word async in your call to mockImplementationOnce(). Then you can remove the type params for jest.spyOn. You don't get type safety within your mock implementation automatically, but if you're really worried about it, you can add as HttpResponse<FeatureFlag>.
let result: FetchResponse<boolean, string>;
describe('getFeatureFlag', () => {
beforeEach(async () => {
// missing
// โ
jest.spyOn(HttpClient, 'get').mockImplementationOnce(async () => ({
ok: true,
data: {
toggleActive: true,
},
} as HttpResponse<FeatureFlag>));
result = await getFeatureFlag(flagName);
})
});
TS Playground
Granted, this doesn't answer the question asked in the title, but it should fix your code. I messed around for a long time trying to get your specified generic type arguments to work, and eventually gave up. It may be a limitation of the declarations in the jest namespace.
Could you try to change your code like this:
jest.spyOn(HttpClient.prototype, 'get').mockImplementationOnce(() => {... return <expectedResultObject>; })
This works for me with the typed-rest-client/RestClient npm package just like charm:
import * as rm from 'typed-rest-client/RestClient';
import {StatusCodes} from 'http-status-codes';
let apiSpy: jest.SpyInstance;
apiSpy = jest.spyOn(rm.RestClient.prototype, 'get');
apiSpy.mockImplementation(path => {
const response: rm.IRestResponse<string> = {
statusCode: StatusCodes.OK,
headers: {},
result: 'stringResult'
}
return response;
})