Impossible de tester les méthodes de publication avec Jest en raison d'une erreur ne peut pas lire mockImplementation of undefined

9

J'ai un service api où j'ai différentes méthodes pour appeler les API. J'ai testé avec succès toutes les demandes GET mais j'ai des problèmes pour tester les demandes POST.

Voici la méthode:

export default class ApiService {
  static makeApiCall = <T>(
    url: string,
    oneCb: <T>(d: Data) => T,
    secondCb: (d: T) => void,
    errorCb?: (a: ErrorModel) => void,
    method = 'get',
    data = {},
  ): Promise<void> => {
    const config: AxiosRequestConfig = {};
    if (method === 'post') {
      config.headers = header;
      return ApiClient.post(url, data, config)
        .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));            
    } else {
      return ApiClient.get(url)
        .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));
    }
  };

  // ONLY ONE POST METHOD TO MAKE IT MORE CLEAR
  static someArchiveMethod = (
    callback: (a: SuccessModel) => void,
    errorCallback: (error: ErrorModel) => void,
    cardId: string
  ): Promise<void> => {
    return ApiService.makeApiCall<SuccessfulResponse>(
      'appreciationCard/archive',
      Normalizer.successfulResponse,
      callback,
      errorCallback,
      'post',
      { cardId }
    );
  };

  // HERE BELOW THE GET METHODS
  static getPeople = (cb: (a: PeopleModel[]) => void, page?: number, limit?: number): Promise<void> => {
    const queryDetails = { page, limit };
    return ApiService.makeApiCall<PeopleModel[]>(
      `people?${toQueryString(queryDetails)}`,
      Normalizer.normalizePeople,
      callback
    );
  };
};

Voici comment je teste tout ce qui concerne les GET:

describe('apiService', () => {
  beforeAll(() => {
    expect(ApiClient.defaults.headers.common.Authorization).toBe('Bearer test token');
    // @ts-ignore
    ApiClient.get.mockImplementation((url: string) => {
      return Promise.resolve({ data: mockData });
    });
  });

  it('should call api client method', () => {
    ApiService.makeApiCall(
      'testUrl',
      data => data,
      res => res,
      err => err,
      'get'
    );

    expect(ApiClient.get).toBeCalledTimes(1);
    expect(ApiClient.get).toBeCalledWith('testUrl');
  });

  it('should call callbacks consequently', done => {
    ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
      expect(firstCallback).toBeCalledTimes(1);
      expect(firstCallback).toBeCalledWith(mockData);
      expect(secondCallback).toBeCalledTimes(1);
      expect(secondCallback).toBeCalledWith(firstCallback(mockData));
      done();
    });
  });
});

describe('api service error flow', () => {
  beforeAll(() => {
    // @ts-ignore
    ApiClient.get.mockImplementation((url: string) => {
      console.log('error result');
      return Promise.reject(mockError);
    });
  });

  it('should handle error', done => {
    console.error = jest.fn();

    const firstCallback = jest.fn((data: any) => data);
    const secondCallback = jest.fn((data: any) => data);

    ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
      expect(firstCallback).toBeCalledTimes(0);
      expect(secondCallback).toBeCalledTimes(0);
      expect(console.error).toBeCalledTimes(1);
      expect(console.error).toBeCalledWith('ApiClient testUrl', mockError);
      done();
    });
  });
});

describe('apiService methods', () => {
  beforeAll(() => {
    ApiClient.get.mockImplementation((url: string) => {
      expect(ApiClient.defaults.headers.common.Authorization).toBe('Bearer test token');

      return Promise.resolve({ data: mockData });
    });
  });

  it('getPeople method call with one param', () => {
    ApiService.getPeople(jest.fn(), 1, 1).then(() => {
      expect(ApiClient.get).toBeCalledWith('people?page=1&limit=1');
    });
  });
})

Je pensais que seulement en changeant toutes les instances de ApiClient.getla , ApiClient.postil travaillera pour tester les requêtes POST. Mais quand j'essaye de le faire, cela dit cela can not read mockImplementation of undefined. J'ai essayé de changer les méthodes dans les tests pour utiliser le postparam afin d'écraser le param method = 'get'mais je n'ai aucun succès, j'obtiens cette erreur

TypeError: apiClient_1.default.post n'est pas une fonction

Des pensées?

Réagir
la source
Une des raisons serait qu'il ApiClientn'a pas de méthode post.
Tomas
Salut, @Tomas regarde cette ligne -> return ApiClient.post(url, data, config) .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));et cela fonctionne correctement lorsque j'essaie de faire une demande de publication. Je veux dire que j'ai comme 17 demandes de messages fonctionnant comme il se doit. Alors pourquoi dans les tests ne fonctionnent pas alors?
Réagissant le
@Reacting Veuillez partager l'exemple de test unitaire "post"
Oron Ben-David
@ OronBen-David J'ai mentionné dans la question que j'ai essayé exactement la même chose que dans le gettest, mais j'ai changé toutes les instances de getet défini à la postplace.
Réagissant le
Je comprends, mais il sera plus clair de mentionner le code qui ne fonctionne pas
Oron Ben-David

Réponses:

5

J'ai enquêté sur votre problème. Tout d'abord, je veux dire que votre code a quelques problèmes comme l'appel de rappel que vous n'avez pas défini, la définition peu claire de ApiClientetc.

J'ai donc créé un exemple Repl pour reproduire votre problème dans lequel j'ai un peu simplifié votre code mais tous les éléments principaux sont là.

S'il vous plaît, jetez un oeil https://repl.it/@SergeyMell/Some-Jesting

Il fonctionne avec succès à la fois getet les postméthodes sans problème. Voici les principaux points sur lesquels vous devez prêter attention:

  1. Utilisation de axiosas ApiClient. (Ce n'était pas clair d'après votre question, j'ai donc supposé qu'il en était ainsi)
    const ApiClient = require('axios');
  2. Activer les moqueries axios(Supposons que vous fassiez de même)
    jest.mock('axios');
  3. Se moquer des deux getet des postdemandes de la même manière (comme à votre façon)

    ApiClient.get.mockImplementation((url) => {
      return Promise.resolve({ data: mockData });
    });
    
    ApiClient.post.mockImplementation((url) => {
      return Promise.resolve({ data: mockData });
    });

Alors, s'il vous plaît, vérifiez mon exemple, vérifiez les différences avec votre code et faites-moi savoir en ce qui concerne certains détalalisations supplémentaires dont vous pourriez avoir besoin.

Sergey Mell
la source
0

Veuillez essayer de passer mockImplementationàmockImplementationOnce

Oron Ben-David
la source