Impossibile verificare i metodi di post con Jest a causa di un errore non è in grado di leggere la simulazione di implementazione non definita


9

Ho un servizio API in cui ho diversi metodi per effettuare chiamate alle API. Ho testato con successo tutte le richieste GET ma ho problemi a testare le richieste POST.

Questo è il metodo:

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
    );
  };
};

Ecco come sto testando tutto ciò che riguarda i 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');
    });
  });
})

Ho pensato che solo cambiando tutte le istanze di ApiClient.getper ApiClient.postil corretto funzionamento per verificare le richieste POST. Ma quando provo a farlo, lo dice can not read mockImplementation of undefined. Ho provato a cambiare i metodi nei test per utilizzare il postparametro al fine di sovrascrivere il parametro method = 'get'ma non ho successo, ottengo questo errore

TypeError: apiClient_1.default.post non è una funzione

qualche idea?


Uno dei motivi sarebbe che ApiClientnon ha metodo post.
Tomas,

Ciao, @Tomas guarda questa riga -> return ApiClient.post(url, data, config) .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));e funziona correttamente quando provo a fare una richiesta post. Voglio dire, ho 17 richieste di post funzionanti come devono. Allora perché nei test non funzionano allora?
Reagendo il

@Reacting Per favore condividi l'esempio "post" del test unitario
Oron Ben-David

@ OronBen-David Ho menzionato nella domanda che ho provato esattamente lo stesso del gettest ma ho invece cambiato tutte le istanze di gete impostate post.
Reazione del

Capisco, ma sarà più chiaro menzionare il codice che non funziona
Oron Ben-David

Risposte:


5

Ho studiato il tuo problema. Prima di tutto, voglio dire che il tuo codice ha un paio di problemi come la richiamata che non hai definito, la definizione poco chiara di ApiClientecc.

Quindi, ho creato un esempio di Repl per riprodurre il tuo problema in cui ho semplificato un po 'il tuo codice ma ci sono tutti gli elementi principali.

Per favore, dai un'occhiata a https://repl.it/@SergeyMell/Some-Jesting

Funziona con successo per entrambi gete postmetodi senza problemi. Ecco i punti principali su cui dovresti prestare attenzione:

  1. Usando axioscome ApiClient. (Non era chiaro dalla tua domanda, quindi ho pensato che fosse così)
    const ApiClient = require('axios');
  2. Impostare scherzi scherzosi axios(Supponiamo che tu faccia lo stesso)
    jest.mock('axios');
  3. Mettendo in giro entrambi gete le postrichieste in modo simile (uguale a modo tuo)

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

Quindi, per favore, controlla il mio esempio, controlla le differenze con il tuo codice e fammi sapere riguardo a qualche ulteriore detalizzazione di cui potresti aver bisogno.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.