ไม่สามารถทดสอบวิธีการโพสต์ด้วย Jest เนื่องจากข้อผิดพลาดไม่สามารถอ่าน mockImplementation ไม่ได้กำหนด


9

ฉันมีบริการ API ที่ฉันมีวิธีการที่แตกต่างกันในการโทรไปยัง API ฉันได้ทดสอบคำขอ GET ทั้งหมดเรียบร้อยแล้ว แต่ฉันประสบปัญหาในการทดสอบคำขอ POST

นี่คือวิธีการ:

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:

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

ผมคิดว่าโดยเฉพาะการเปลี่ยนแปลงทุกกรณีของApiClient.getการApiClient.postมันจะทำงานเพื่อทดสอบการร้องขอการโพสต์ can not read mockImplementation of undefinedแต่เมื่อฉันพยายามที่จะทำอย่างนั้นก็กล่าวว่า ฉันลองเปลี่ยนวิธีในการทดสอบเพื่อใช้postพารามิเตอร์เพื่อเขียนทับพารามิเตอร์method = 'get'แต่ฉันไม่ประสบความสำเร็จฉันได้รับข้อผิดพลาดนี้

TypeError: apiClient_1.default.post ไม่ใช่ฟังก์ชั่น

ความคิดใด ๆ


หนึ่งในเหตุผลที่จะเป็นที่ไม่ได้มีวิธีการApiClient post
โทมัส

สวัสดี @Tomas ดูที่บรรทัดนี้ -> return ApiClient.post(url, data, config) .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));และทำงานอย่างถูกต้องเมื่อฉันพยายามส่งคำขอโพสต์ ฉันหมายถึงฉันมีคำขอโพสต์ 17 รายการที่ทำงานได้ตามที่ต้องการ เหตุใดในการทดสอบจึงไม่ทำงาน
ทำปฏิกิริยา

@ Reacting กรุณาแชร์ตัวอย่างการทดสอบ "โพสต์"
Oron Ben-David

@ OronBen-David ฉันพูดถึงในคำถามที่ฉันพยายามเหมือนกันในการgetทดสอบ แต่ฉันเปลี่ยนอินสแตนซ์ทั้งหมดgetและตั้งค่าpostแทน
ทำปฏิกิริยา

ฉันเข้าใจ แต่จะชัดเจนยิ่งขึ้นเมื่อพูดถึงรหัสที่ไม่ทำงาน
Oron Ben-David

คำตอบ:


5

ฉันตรวจสอบปัญหาของคุณแล้ว ก่อนอื่นผมอยากจะบอกว่ารหัสของคุณมีปัญหาสองสามอย่างเช่นการโทรกลับที่คุณไม่ได้กำหนดไม่ชัดเจนการกำหนดApiClientฯลฯ

ดังนั้นฉันจึงสร้างตัวอย่าง Repl เพื่อทำซ้ำปัญหาของคุณซึ่งฉันทำให้โค้ดของคุณง่ายขึ้นเล็กน้อย แต่องค์ประกอบหลักทั้งหมดอยู่ที่นั่น

โปรดดู https://repl.it/@SergeyMell/Some-Jesting

มันทำงานได้สำเร็จทั้งสำหรับgetและpostวิธีการไม่มีปัญหา นี่คือประเด็นหลักที่คุณควรให้ความสนใจ:

  1. ใช้เป็นaxios ApiClient(มันไม่ชัดเจนจากคำถามของคุณดังนั้นฉันคิดว่ามันเป็นอย่างนั้น)
    const ApiClient = require('axios');
  2. การตั้งค่าล้อเลียนล้อเล่นบนaxios(สมมติว่าคุณทำเช่นเดียวกัน)
    jest.mock('axios');
  3. ใส่ mocks ให้ทั้งสองgetและpostร้องขอในลักษณะที่คล้ายกัน (เช่นเดียวกับวิธีการของคุณ)

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

ดังนั้นโปรดตรวจสอบตัวอย่างของฉันตรวจสอบความแตกต่างด้วยรหัสของคุณและแจ้งให้เราทราบเกี่ยวกับการหารายละเอียดเพิ่มเติมที่คุณอาจต้องการ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.