在componentDidMount()中设置时如何模拟eventListener

时间:2019-02-12 10:51:19

标签: javascript reactjs jestjs enzyme

那是我的组成部分

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   上面的错误发生在组件中:   在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;
    })

在测试中安装<Foo />之前。但这一切都返回相同的错误。为什么会这样?

1 个答案:

答案 0 :(得分:0)

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();
...