Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
When using
jest.fn()
to add a mock you can usually access the
.mock
property to access details such as calls, something similar to this:
test('not working', () => {
const foo = new Foo();
foo.addListener = jest.fn();
foo.func(); // will call addListener with a callback
const callback = foo.addListener.mock.calls[0][0];
expect(callback()).toEqual(1); // test the callback
When implementing the test in typescript instead of plain javascript I get the error:
error TS2339: Property 'mock' does not exist on type '(callback: () => number) => void'.
I can get rid of the error by casting to any but surely there must be a better way:
const callback = (foo.addListener as any).mock.calls[0][0];
In this simple code the mock could be rewritten to store the argument using jest.fn(fn => { callback = fn; }); but the same error happens when using foo.addListener.mockClear() which cannot be reworked the same way.
So how can I get rid of the error, preferably without losing type-safety?
For anyone getting here, a bit better than casting to any might be casting as jest.Mock
const callback = (foo.addListener as jest.Mock).mock.calls[0][0];
Update Sep 2021
To get a mocked function that both fulfills the mocked function type and the jest mock type jest.MockedFunction can be used:
const addListenerMock = addListener as jest.MockedFunction<typeof addListener>;
You can use jest.spyOn in combination with functions like mockImplementation to mock a function while preserving type safety in TypeScript:
class Foo {
addListener = (callback: () => number) => { }
func = () => {
this.addListener(() => 1);
test('working', () => {
const foo = new Foo();
const mockAddListener = jest.spyOn(foo, 'addListener'); // spy on foo.addListener
mockAddListener.mockImplementation(() => { }); // replace the implementation if desired
foo.func(); // will call addListener with a callback
const callback = mockAddListener.mock.calls[0][0];
expect(callback()).toEqual(1); // SUCCESS
–
Got the error below when using axios.
TS2339 (TS) Property 'mockResolvedValueOnce' does not exist on type
'AxiosStatic'
Tried using axios as jest.Mock but got the error below:
TS2352 (TS) Conversion of type 'AxiosStatic' to type 'Mock<any, any>'
may be a mistake because neither type sufficiently overlaps with the
other. If this was intentional, convert the expression to 'unknown'
first. Type 'AxiosStatic' is missing the following properties from
type 'Mock<any, any>': getMockName, mock, mockClear, mockReset, and 12
more.
Solved it by specifying as axios as unknown as jest.Mock
AxiosRequest.test.tsx
import axios from 'axios';
import { MediaByIdentifier } from '../api/mediaController';
jest.mock('axios', () => jest.fn());
test('Test AxiosRequest',async () => {
const mRes = { status: 200, data: 'fake data' };
(axios as unknown as jest.Mock).mockResolvedValueOnce(mRes);
const mock = await MediaByIdentifier('Test');
expect(mock).toEqual(mRes);
expect(axios).toHaveBeenCalledTimes(1);
mediaController.ts:
import { sendRequest } from './request'
import { AxiosPromise } from 'axios'
import { MediaDto } from './../model/typegen/mediaDto';
const path = '/api/media/'
export const MediaByIdentifier = (identifier: string): AxiosPromise<MediaDto> => {
return sendRequest(path + 'MediaByIdentifier?identifier=' + identifier, 'get');
request.ts:
import axios, { AxiosPromise, AxiosRequestConfig, Method } from 'axios';
const getConfig = (url: string, method: Method, params?: any, data?: any) => {
const config: AxiosRequestConfig = {
url: url,
method: method,
responseType: 'json',
params: params,
data: data,
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' },
return config;
export const sendRequest = (url: string, method: Method, params?: any, data?: any): AxiosPromise<any> => {
return axios(getConfig(url, method, params, data))
jest.spyOn is the right way to go.
However, if you'd like to do the same with a simple function that's not a part of a class, you can use jest.mocked. Here's an example importing functions from Firebase:
/** Example code depending on a simple function */
import {
addDoc, // Function to be mocked
collection,
getFirestore
} from 'firebase/firestore';
export async function createRecord(record: any) {
const collectionRef = collection(getFirestore(), 'example-path');
return addDoc(collectionRef, record);
/** Unit tests for example code */
import { addDoc } from 'firebase/firestore';
jest.mock('firebase/firestore');
describe('Create record', () => {
test('creates a new record', async () => {
const mockedAddDoc = jest.mocked(addDoc);
await createRecord({ hello: 'world' });
expect(mockedAddDoc.mock.calls[0][0]).toMatchObject({ hello: 'world' });
https://jestjs.io/docs/jest-object#jestmockedtitem-t-deep--false
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.