Tìm kiếm trang web

javascript - Làm thế nào để kiểm tra useEffect bên trong một hook tùy chỉnh?


Vì vậy, tôi khá mới với việc test trong React. Tôi có một hook tùy chỉnh mà tôi đang gọi bên trong một component. Tôi đang sử dụng các phương thức renderHook từ react-hook-testing-library.

Tôi cần kiểm tra xem các phương thức bên trong useEffect trong hook tùy chỉnh có được gọi hay không. Tôi dường như không thể tìm ra cách làm điều này.

Trong một trường hợp khác, tôi cần tìm cách xác định xem trackPdpGtm có bị gọi hay không.

Lưu ý: Hook này không trả về bất kỳ dữ liệu nào. Điều này chủ yếu để gửi thông tin phân tích.

Cách tiếp cận hiện tại:

usePdpGtm.js

import { useEffect } from 'react';
import { trackPdpGtm } from 'utils/gtm/pdpGtmUtils';
import _ from 'utils/lodashImports';

export default function useGtmPdp(data = {}) {
  console.log('are you getting called?');
  const { relatedProducts, results, priceInfo, breadcrumbs } = data;
  const relatedProductsLoaded = _.get(relatedProducts, 'relatedProductsLoaded');
  useEffect(() => {
     if (relatedProductsLoaded) {
         trackPdpGtm(data);
     }
  }, [relatedProductsLoaded, results, priceInfo, breadcrumbs]);
}

Tôi cần kiểm tra xem trackPdpGtm có được gọi hay không. Cũng cần kiểm tra rằng nó không được gọi trong một trường hợp kiểm tra khác.

gtm.test.js

import { renderHook, cleanup, act } from 'react-hooks-testing-library';
import usePdpGtm from 'utils/hooks/gtmHooks/usePdpGtm';
import useListPageGtm from 'utils/hooks/gtmHooks/useListPageGtm';
import { trackPdpGtm } from 'utils/gtm/pdpGtmUtils';
import { trackListPageGtm } from 'utils/gtm/plpGtmUtils';
import { mount, shallow } from 'enzyme';
import { ProductDescriptionComponent } from 'components/business/ProductDescription/ProductDescriptionComponent';

jest.mock('utils/hooks/gtmHooks/usePdpGtm');
jest.mock('utils/hooks/gtmHooks/useListPageGtm');
jest.mock('utils/gtm/pdpGtmUtils');
jest.mock('utils/gtm/plpGtmUtils');

trackPdpGtm.mockImplementation = jest.fn();
// ALSO TRIED trackPdpGtm.mockImplementation(() => jest.fn());
trackListPageGtm.mockImplementation(() => console.log('adadada'));

describe('analytics helper', () => {
  afterEach(cleanup);

  it('should fire usePdpGtm Hook', async (done) => {
    const pdpData = {
      relatedProducts: {
        collectionProducts: [],
        relatedProductsLoaded: true
      },
      productInfo: {
        variants: [{}],
        breadcrumbs: [{}],
        serviceWarrantyDetails: {
          services: [],
          warranties: [{}]
        }
      },
      priceInfo: [{}],
      breadcrumbs: [{}]
    };
    const { result } = renderHook(() => usePdpGtm(pdpData));
    //THIS IS FAILING
    expect(trackPdpGtm).toHaveBeenCalledTimes(1);
    expect(result.current).toBeUndefined();
  });

   it('should fire usePdpGtm Hook without data', () => {
     const { result } = renderHook(() => usePdpGtm(undefined));
    
     // NEED TO TEST IF trackPdpGtm is NOT called. (also failing)

     expect(trackPdpGtm).toNotBeCalled();
     expect(result.current).toBeUndefined();
   });

});

Cũng đã thử sử dụng trackGtmPdp.mock.calls.length.toBe(1).

Hook usePdpGtm được gọi bên trong ProductDescriptionComponent và nhận một đối tượng làm tham số.

Lưu ý: Hook tùy chỉnh không chạy trong quá trình kiểm thử. Tôi không chắc nhưng các câu lệnh console.log bên trong không được in ra khi kiểm thử đang chạy.

Bất cứ sự giúp đỡ nào cũng đều được đánh giá cao.

Câu trả lời #1

Bạn quên xóa các thuộc tính mock.calls và mock.instances của mock hàm trackPdpGtm. Đó là lý do tại sao trường hợp kiểm tra thứ hai của bạn thất bại. Bạn có thể sử dụng jest.clearAllMocks() để xóa chúng trong hook afterEach.

Ví dụ

usePdpGtm.ts:

// @ts-nocheck
import { useEffect } from 'react';
import { trackPdpGtm } from './pdpGtmUtils';
import _ from 'lodash';

export default function useGtmPdp(data = {}) {
  console.log('are you getting called?');
  const { relatedProducts, results, priceInfo, breadcrumbs } = data;
  const relatedProductsLoaded = _.get(relatedProducts, 'relatedProductsLoaded');
  useEffect(() => {
    if (relatedProductsLoaded) {
      trackPdpGtm(data);
    }
  }, [relatedProductsLoaded, results, priceInfo, breadcrumbs]);
}

pdpGtmUtils.ts:

export function trackPdpGtm(data) {
  console.log('real track pdp gtm implementation');
}

usePdpGtm.test.ts:

import { renderHook, cleanup } from '@testing-library/react-hooks';
import usePdpGtm from './usePdpGtm';
import { trackPdpGtm } from './pdpGtmUtils';

jest.mock('./pdpGtmUtils');

describe('analytics helper', () => {
  afterEach(() => {
    jest.clearAllMocks();
    cleanup();
  });

  it('should fire usePdpGtm Hook', () => {
    const pdpData = {
      relatedProducts: {
        collectionProducts: [],
        relatedProductsLoaded: true,
      },
      productInfo: {
        variants: [{}],
        breadcrumbs: [{}],
        serviceWarrantyDetails: {
          services: [],
          warranties: [{}],
        },
      },
      priceInfo: [{}],
      breadcrumbs: [{}],
    };
    const { result } = renderHook(() => usePdpGtm(pdpData));
    expect(trackPdpGtm).toHaveBeenCalledTimes(1);
    expect(result.current).toBeUndefined();
  });

  it('should fire usePdpGtm Hook without data', () => {
    const { result } = renderHook(() => usePdpGtm(undefined));
    expect(trackPdpGtm).not.toBeCalled();
    expect(result.current).toBeUndefined();
  });
});

kết quả kiểm thử đơn vị:

 PASS  examples/65703648/usePdpGtm.test.ts
  analytics helper
    ✓ should fire usePdpGtm Hook (28 ms)
    ✓ should fire usePdpGtm Hook without data (4 ms)

  console.log
    are you getting called?

      at Object.useGtmPdp [as default] (examples/65703648/usePdpGtm.ts:7:11)

  console.log
    are you getting called?

      at Object.useGtmPdp [as default] (examples/65703648/usePdpGtm.ts:7:11)

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |   91.67 |      100 |   66.67 |   91.67 |                   
 pdpGtmUtils.ts |      50 |      100 |       0 |      50 | 2                 
 usePdpGtm.ts   |     100 |      100 |     100 |     100 |                   
----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        5.167 s