首页 > 解决方案 > 如何在 React 中用 Jest 和 Enzyme 测试这样的组件?

问题描述

我有一个 React Scroll to Top 组件,我们将这个组件添加到我们的路由器下方,以便在跨页面移动时我们不保持滚动位置。

我试图为此组件编写测试用例,但是在进行浅层渲染时,Jest 和 Enzyme dosent 似乎将其识别为组件。我正在使用打字稿,这是组件。

scrollToTop.ts

export const ScrollToTop = ({history}: IRouterResetScroll) => {
  useEffect(() => {
    const unListen = history.listen(() => {
      window.scrollTo(0, 0);
    });
    return () => {
      unListen();
    }
  }, []);

  return null;
}

export default withRouter(ScrollToTop);

标签: reactjsjestjsenzyme

解决方案


这是我的单元测试策略,要测试的代码最难的部分是history.listen(handler),所以我们可以模拟history.listen方法的实现,我们定义了 aqueue来存储处理程序。挂载组件后,模拟历史将以history.listen函数作为参数执行。这个函数会保存在queue我们之前定义的里面。我们可以从单元测试用例的队列中获取这个函数并手动触发它。

index.tsx

import { useEffect } from 'react';
import { withRouter } from 'react-router-dom';

type IRouterResetScroll = any;

export const ScrollToTop = ({ history }: IRouterResetScroll) => {
  useEffect(() => {
    const unListen = history.listen(() => {
      window.scrollTo(0, 0);
    });
    return () => {
      unListen();
    };
  }, []);

  return null;
};

export default withRouter(ScrollToTop);

index.spec.tsx

import React from 'react';
import { ScrollToTop } from './';
import { mount } from 'enzyme';

describe('ScrollToTop', () => {
  it('should scroll to top', () => {
    const queue: any[] = [];
    const mUnListen = jest.fn();
    const mHistory = {
      listen: jest.fn().mockImplementation(fn => {
        queue.push(fn);
        return mUnListen;
      })
    };
    window.scrollTo = jest.fn();
    const wrapper = mount(<ScrollToTop history={mHistory}></ScrollToTop>);
    queue[0]();
    expect(mHistory.listen).toBeCalledWith(expect.any(Function));
    expect(window.scrollTo).toBeCalledWith(0, 0);

    wrapper.unmount();
    expect(mUnListen).toBeCalledTimes(1);
  });
});

覆盖率 100% 的单元测试结果:

 PASS  src/stackoverflow/58786973/index.spec.tsx
  ScrollToTop
    ✓ should scroll to top (39ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.041s, estimated 9s

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58786973


推荐阅读