Hata nedeniyle Jest ile post yöntemleri test edilemedi mock okunamıyor


9

API'ları arama yapmak için farklı yöntemler var bir api hizmetim var. Tüm GET isteklerini başarıyla test ettim ancak POST isteklerini test etmede sorunlar yaşıyorum.

Bu yöntem:

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

GET'lerle ilgili her şeyi şu şekilde test ediyorum:

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

Sadece örnekleri tüm değiştirerek düşündük ApiClient.getiçin ApiClient.postkendisine POST isteklerini test etmek için çalışacaktır. Ama bunu yapmaya çalıştığımda bunu söylüyor can not read mockImplementation of undefined. postParamın üzerine yazmak için param kullanmak için testlerdeki yöntemleri değiştirmeyi denedim method = 'get'ama başarılı olamıyorum, bu hatayı alıyorum

TypeError: apiClient_1.default.post bir işlev değil

Düşüncesi olan var mı?


Sebeplerden biri, ApiClientyöntemin olmamasıdır post.
Tomas

Merhaba, @Tomas bu satıra bak -> return ApiClient.post(url, data, config) .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));ve bir posta isteği yapmaya çalıştığımda düzgün çalışıyor. Demek istediğim, gerektiği gibi çalışan 17 gönderi isteği var. Öyleyse neden testlerde o zaman çalışmıyor?
tepki gösteren

@Reacting Lütfen "post" birim test örneğini paylaşın
Oron Ben-David

@ OronBen-David Ben testte tam olarak aynı denedim soruda bahsetti getama yerine tüm örneklerini değiştirdim getve ayarlayın post.
tepki gösteren

Anlıyorum, ama çalışmayan koddan bahsetmek daha açık olacak
Oron Ben-David

Yanıtlar:


5

Sorununu araştırdım. Her şeyden önce, kodunuzun tanımlamadığınız geri arama, net olmayan tanımlama ApiClientvb. Gibi birkaç sorunu olduğunu söylemek istiyorum .

Bu nedenle, kodunuzu biraz basitleştirdiğim ancak tüm ana öğeler orada olan sorununuzu yeniden oluşturmak için bir Repl örneği oluşturdum.

Lütfen bir göz atın https://repl.it/@SergeyMell/Some-Jesting

Hiçbir sorun olmadan hem getve postyöntemler için başarıyla çalışır . Burada, dikkat etmeniz gereken ana noktalar şunlardır:

  1. Kullanılması axiosolarak ApiClient. (Sorunuz net değildi, bu yüzden öyle olduğunu varsaydım)
    const ApiClient = require('axios');
  2. Joket alayları devreye sokma axios(Diyelim ki aynı şeyi yapıyorsunuz)
    jest.mock('axios');
  3. Her ikisine de alay getve postistekleri benzer şekilde koymak (aynı şekilde)

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

Lütfen, örneğimi kontrol edin, kodunuzdaki farklılıkları kontrol edin ve ihtiyacınız olabilecek ek detalizasyonla ilgili olarak bana bildirin.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.