【问题标题】:jest/enzyme test event listener removed开玩笑/酶测试事件侦听器已删除
【发布时间】:2018-10-15 09:02:03
【问题描述】:

学习 jest 和酶以测试 react 应用,使用 create-react-app 引导。

shallow 之后使用unmount 模拟add/removeEventListener 崩溃,并在mount 之后使用unmount 发出警告,见下文。有谁知道我做错了什么?

我的测试:

it('should add and remove resize event handler', () => {
  const adder = jest
    .spyOn(global, 'addEventListener')
    .mockImplementation(() => {});
  const remover = jest
    .spyOn(global, 'removeEventListener')
    .mockImplementation(() => {});
  const wrapper = shallow(<App />);
  // this seems to work
  expect(adder).toHaveBeenCalled();
  // causing issues
  wrapper.unmount();
  expect(remover).toHaveBeenCalled();
});

mount 之后使用unmount

  console.error node_modules/fbjs/lib/warning.js:33
    Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

    Please check the code for the App component.

shallow 之后使用unmount

/home/nik/projects/learn/jest/node_modules/react-scripts/scripts/test.js:20
  throw err;
  ^

Invariant Violation: ReactShallowRenderer render(): Invalid component element.
    at invariant (/home/nik/projects/learn/jest/node_modules/fbjs/lib/invariant.js:42:15)
    at ReactShallowRenderer.render (/home/nik/projects/learn/jest/node_modules/enzyme-adapter-react-16/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:104:38)
    at Updater.enqueueSetState (/home/nik/projects/learn/jest/node_modules/enzyme-adapter-react-16/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:329:20)
    at App.Object.<anonymous>.Component.setState (/home/nik/projects/learn/jest/node_modules/react/cjs/react.development.js:237:16)
    at loadData.then.results (/home/nik/projects/learn/jest/src/App.js:15:12)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
error An unexpected error occurred: "Command failed.
Exit code: 1
Command: sh
Arguments: -c react-scripts test --env=jsdom
Directory: /home/nik/projects/learn/jest
Output:
".
info If you think this is a bug, please open a bug report with the information provided in "/home/nik/projects/learn/jest/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

【问题讨论】:

标签: reactjs jestjs enzyme create-react-app


【解决方案1】:

我将卸载包装在承诺中

  return Promise.resolve().then(() => {
    wrapper.unmount();
    expect(remover).toHaveBeenCalled();
  });

还遗漏了错误中的一个线索,“loadData” - 不是在模拟:

  jest.spyOn(App.prototype, 'loadData')
    .mockImplementation(() => {
      return new Promise(resolve => resolve([topics, subTopics]))
    });

【讨论】:

    【解决方案2】:

    要解决第一个问题,必须采取措施避免在卸载组件后调用setState

    解决此问题的更简单方法是维护_isMounted 标志,您将在调用 setState 之前检查该标志:

    componentDidMount() {
      this._isMounted = true;
    
      this.loadData().then(results => {
        if (!this._isMounted) {
          return;
        }
    
        const [topics, subTopics, ...rest] = results;
    
        this.setState({ topics, subTopics });
      });
    
      window.addEventListener('resize', this.someHandler);
    }
    
    componentWillUnmount() {
      this._isMounted = false;
    
      window.removeEventListener('resize', this.someHandler);
    }
    

    您可以在 React 博客中阅读有关此问题的更多信息并找到另一个解决方案:https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html

    【讨论】:

    • 我不喜欢你的解决方案,抱歉......但这让我开始思考为什么我在...Unmount 中调用 setState。我想也许我太早打电话给unmount 所以把它包装在一个回报Promise.resolve().then() 中,它似乎工作,虽然我不敢相信我还没有尝试过。
    猜你喜欢
    • 2021-01-05
    • 2019-09-13
    • 2018-07-22
    • 2023-03-27
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多