【问题标题】:Jest mocking with Next useRouter用 Next useRouter 开玩笑
【发布时间】:2022-01-06 13:12:37
【问题描述】:

这是我正在测试的文件 -

import React from 'react';
import { useRouter } from 'next/router';
import Item from '../Item';
import { getBaseURL } from '../../utils/url';
import { usePath } from '../../hooks/usePath';
import ITEMS from '../../constants/items';
import styles from './itemlist.module.scss';

const ItemList = () => {
  const router = useRouter();
  const path = usePath();
  const queryIndex = router?.asPath?.lastIndexOf('?') || -1;
  const query = queryIndex !== -1 ? router.asPath.slice(queryIndex) : '';

  return (
    <div className={styles.itemWrapper}>
      <h2 className={styles.title}>Popular Items</h2>
      <div className={styles.itemList}>
        {ITEMS.map(({ name, url }) => (
          <Item
            key={name}
            name={name}
            url={`${getBaseURL()}${url}${query}`}
            active={path === url}
          />
        ))}
      </div>
    </div>
  );
};

export default ItemList;

这是我目前在测试文件中的内容 -

/* eslint-disable camelcase */
/* eslint-env jest */
import { shallow } from 'enzyme';
import ItemList from '.';
import usePath from '../../hooks/usePath';

jest.mock('../../hooks/usePath');
jest.mock('next/router');
jest.mock('../../utils/url');
jest.mock('../../constants/items');

describe('ItemList Component', () => {
  it('should mount without an error', () => {
    const shallowRender = shallow(<ItemList />);
    expect(shallowRender.exists()).toBe(true);
  });

  it('should form the page url links including any existing query string', () => {
    const shallowRender = shallow(<ItemList />);
    expect(
      shallowRender
        .find('Item')
        .at(0)
        .prop('url')
    ).toEqual('// Not sure how to test this');
  });

  // it('should make the current url active', () => {
  // });
});

我想测试的是它是否形成/传递了正确的 url 到 Item 组件,以及如果路径与 url 匹配,它是否使 Item 组件处于活动状态。

我不确定如何最好地模拟这个?我已经开始为第一个场景编写测试,但我认为 usePath 和 useRouter 需要以某种方式进行模拟。

这是 usePath 文件 -

const getPath = router =>
  router.pathname.includes('[item]')
    ? router.pathname.replace('[item]', router.query.item)
    : router.pathname;

export const usePath = () => {
  const router = useRouter();

  return getPath(router);
};

【问题讨论】:

    标签: reactjs unit-testing react-hooks jestjs enzyme


    【解决方案1】:

    一种选择是模拟 ITEMS 和 useRouter 挂钩,以便检查组件是否正确呈现:

    it('should form the page url links including any existing query string', () => {
        const name = 'Name';
        const url = 'Url';
        ITEMS = [{ name, url }];
        const shallowRender = shallow(<ItemList />);
        const renderItem = shallowRender.find('Item').at(0);
        expect(renderItem.prop('url')).toEqual(url);
        expect(renderItem.prop('name')).toEqual(name);
      });
    

    对于主动测试,您必须模拟 usePath:

    jest.mock('../../hooks/usePath', () => ({
      usePath: jest.fn(),
    }));
    

    所以你可以尝试这样做:

    it('should make the current url active', () => {
        const name = 'Name';
        const url = 'Url';
        ITEMS = [{ name, url }];
        usePath.mockImplementation(() => url);
        const shallowRender = shallow(<ItemList />);
        const renderItem = shallowRender.find('Item').at(0);
        expect(renderItem.prop('active')).toEqual(true);
      });
    

    对于非活动测试:

    it('should make other url not active', () => {
        const name = 'Name';
        const url = 'Url';
        ITEMS = [{ name, url }];
        usePath.mockImplementation(() => 'otherUrl');
        const shallowRender = shallow(<ItemList />);
        const renderItem = shallowRender.find('Item').at(0);
        expect(renderItem.prop('active')).toEqual(false);
      });
    

    同时,您可以根据需要模拟 useRoute。例如:

    jest.mock('next/router');
    

    在测试中你可以模拟如下:

    useRouter.mockImplementation(()=>({pathname:'', ......}))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      • 1970-01-01
      • 2017-08-25
      • 2018-12-10
      • 2022-08-07
      • 2021-06-20
      • 1970-01-01
      相关资源
      最近更新 更多