0

I am trying to mock a function named callApi. I use jest.fn(), but I am having the error message:

function callApi(method: string, url: string, path: string, data?: any): Promise> Cannot assign to 'callApi' because it is a read-only property.ts(2540)

I have tried to follow the examples on jest examples

What is wrong with my code? Why am I having the error message.
Part of callApi is import axios from "axios";

export function callApi(
  method: string,
  url: string,
  path: string,
  data?: any
) {
  switch (method) {

The test is as follows:

import {runSaga} from 'redux-saga';
import * as api from '../Utilities/api'
import { getPaymentsError, getPaymentsSuccess, IPaymentsAction } from './actions';
import handleFetch from './sagas'


test('should test fetch payments success',async() =>{
const dispatchedActions = [{}];
const mockedPayments = [{
    details: {
    amount: "10000",
    date: new Date(),
    id: 5
  },
  id: 5,
  month: "Feb 2003",
  userID: 3
}];


 api.callApi = jest.fn(() => Promise.resolve(mockedPayments));<----------error here



const fakeStore = {
    dispatch:(action:IPaymentsAction) =>dispatchedActions.push(action)
}
await runSaga(fakeStore,handleFetch).done;
expect(api.callApi.mock.calls.length).toBe(1);
expect(dispatchedActions).toContainEqual(getPaymentsSuccess(mockedPayments));
})

1 Answers1

4

Assigning to a jest.fn() doesn't work well with TypeScript typing.

Use jest.spyOn instead:

test('should test fetch payments success', async (done) => {
  const dispatchedActions = [{}];
  const mockedPayments = [{
    details: {
      amount: "10000",
      date: new Date(),
      id: 5
    },
    id: 5,
    month: "Feb 2003",
    userID: 3
  }];

  const spy = jest.spyOn(api, 'callApi');
  spy.mockImplementation(() => Promise.resolve(mockedPayments));

  const fakeStore = {
    dispatch: (action: IPaymentsAction) => dispatchedActions.push(action)
  }
  await runSaga(fakeStore, handleFetch);done();
  expect(spy.mock.calls.length).toBe(1);
  expect(dispatchedActions).toContainEqual(getPaymentsSuccess(mockedPayments));
})
Brian Adams
  • 43,011
  • 9
  • 113
  • 111
  • I am having the error Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. at pTimeout (node_modules/jest-jasmine2/build/queueRunner.js:53:21) at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:523:19) – jupiter sailormoon Mar 21 '19 at 02:27
  • @jupitersailormoon that is a separate issue (sounds like your saga might not be resolving) and should be addressed in a new question if help is needed. – Brian Adams Mar 21 '19 at 02:36
  • I have added the done function . Thanks to https://stackoverflow.com/questions/49603939/async-callback-was-not-invoked-within-the-5000ms-timeout-specified-by-jest-setti and thanks @brian-lives-outdoors – jupiter sailormoon Mar 21 '19 at 03:21
  • After hours of searching, this answer saved me from slamming my keyboard off my desk. THANK YOU! – Borduhh Apr 13 '20 at 01:08