【问题标题】:How to mock eventListener when set in componentDidMount()在 componentDidMount() 中设置时如何模拟 eventListener
【发布时间】:2019-07-06 00:00:58
【问题描述】:

这是我的组件

class Foo extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            ...
        };

        this.input = React.createRef();
    }

    componentDidMount() {
        const id = 'bar';
        let element = document.getElementById(id);
        element.addEventListener('transitionend', () => {
            this.setState({ ... });
        }, false);
    }

    ...

当我这样设置测试时

import React from 'react';
import { mount } from 'enzyme';
import 'jsdom-global/register';

import Foo from './';

it('renders the component correctly', () => {
    const component = mount(
        <Foo />
    );

    component
        .unmount();
});

我明白了

console.error node_modules/react-dom/cjs/react-dom.development.js:16647 组件出现上述错误: in Foo(由 WrapperComponent 创建) 在 WrapperComponent 中

考虑在树中添加错误边界以自​​定义错误处理行为。 ● 正确渲染组件 TypeError:无法读取 null 的属性“addEventListener”

我试过了

ReactDOM.render(<Foo />, document.body);

或者添加这个

const map = {};
Window.addEventListener = jest.genMockFn().mockImpl((event, cb) => {
  map[event] = cb;
});

还有这个

const map = {};
    document.addEventListener = jest.fn((event, cb) => {
      map[event] = cb;
    })

在测试中安装 &lt;Foo /&gt; 之前。但这一切都带来了同样的错误。这是为什么呢?

【问题讨论】:

标签: javascript reactjs jestjs enzyme


【解决方案1】:

在 React 中不鼓励直接 DOM 访问的原因之一是因为它使测试变得更加复杂和不可预测。

可以在安装组件之前完全模拟 DOM:

const elementMock = { addEventListener: jest.fn() };
jest.spyOn(document, 'getElementById').mockImplementation(() => elementMock);

可以测试被正确调用的存根:

expect(elementMock.addEventListener).toBeCalledWith('transitionend', expect.any(Function), false);

并且可以测试事件监听器是否按预期改变了状态:

const handler = elementMock.mock.calls[0][1];
handler();
...

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 2015-06-25
相关资源
最近更新 更多