代码之家  ›  专栏  ›  技术社区  ›  four-eyes

在componentdidmount()中设置时如何模拟EventListener

  •  0
  • four-eyes  · 技术社区  · 6 年前

    那是我的组件

    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节点_modules/react dom/cjs/react dom.development.js:16647 组件中发生上述错误: 在foo中(由wrappercomponent创建) 包装组件中

    考虑向树中添加错误边界以自定义错误处理行为。 正确呈现组件 类型错误:无法读取空的属性“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 回复  |  直到 6 年前
        1
  •  0
  •   Estus Flask    6 年前

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