Tidak dapat menguji metode posting dengan Jest karena kesalahan tidak dapat membaca mockImplementation yang tidak terdefinisi

9

Saya memiliki layanan api di mana saya memiliki metode berbeda untuk melakukan panggilan ke API. Saya telah berhasil menguji semua permintaan GET tetapi saya mengalami masalah dalam menguji permintaan POST.

Inilah metodenya:

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

Ini adalah bagaimana saya menguji segala sesuatu yang berkaitan dengan 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');
    });
  });
})

Saya berpikir bahwa hanya dengan mengubah semua instance ApiClient.getuntuk ApiClient.postitu akan berfungsi untuk menguji permintaan POST. Tetapi ketika saya mencoba melakukan itu dikatakan demikian can not read mockImplementation of undefined. Saya mencoba mengubah metode dalam tes untuk menggunakan postparam untuk menimpa param method = 'get'tetapi saya tidak berhasil, saya mendapatkan kesalahan ini

TypeError: apiClient_1.default.post bukan fungsi

Adakah pikiran?

Bereaksi
sumber
Salah satu alasannya adalah karena ApiClienttidak memiliki metode post.
Tomas
Hai, @Tomas lihat baris ini -> return ApiClient.post(url, data, config) .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));dan berfungsi dengan baik ketika saya mencoba melakukan permintaan posting. Maksud saya, saya memiliki 17 permintaan pos yang berfungsi sebagaimana mestinya. Jadi mengapa dalam tes tidak berhasil?
Bereaksi
@Bereaksi Tolong bagikan contoh tes unit "post"
Oron Ben-David
@ OronBen-David Saya sebutkan dalam pertanyaan bahwa saya mencoba persis sama seperti dalam gettes tetapi saya mengubah semua contoh getdan mengatur postsebagai gantinya.
Bereaksi
Saya mengerti, tetapi akan lebih jelas untuk menyebutkan kode yang tidak berfungsi
Oron Ben-David

Jawaban:

5

Saya sudah menyelidiki masalah Anda. Pertama-tama, saya ingin memberi tahu bahwa kode Anda memiliki beberapa masalah seperti menelepon kembali yang tidak Anda tetapkan, tidak jelas mendefinisikan ApiClientdll.

Jadi, saya membuat contoh Repl untuk mereproduksi masalah Anda di mana saya menyederhanakan kode Anda tetapi semua elemen utama ada di sana.

Silakan, lihat https://repl.it/@SergeyMell/Some-Jesting

Ia bekerja dengan sukses untuk keduanya getdan postmetode tanpa masalah. Di sini, adalah poin utama yang harus Anda perhatikan:

  1. Menggunakan axiossebagai ApiClient. (Tidak jelas dari pertanyaan Anda jadi saya berasumsi begitu)
    const ApiClient = require('axios');
  2. Mengatur gurauan mengejek pada axios(Misalkan, Anda melakukan hal yang sama)
    jest.mock('axios');
  3. Menempatkan ejekan untuk keduanya getdan postmeminta dengan cara yang sama (sama dengan cara Anda)

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

Jadi, tolong, periksa contoh saya, periksa perbedaannya dengan kode Anda dan beri tahu saya mengenai beberapa detalization tambahan yang mungkin Anda butuhkan.

Sergey Mell
sumber
0

Silakan coba ubah mockImplementationkemockImplementationOnce

Oron Ben-David
sumber