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
                The only catch to this approach is  you need to import the whole library as in import * as _ from '', because the spy is applied to an object.
– windmaomao
                Apr 16 at 14:44

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.