如何模拟/间谍在ReactJS的ref上调用的addEventListener方法?

时间:2019-09-15 11:20:40

标签: reactjs testing jestjs enzyme snapshot

我正在对在其div上具有引用的一个组件进行快照测试。该组件看起来像-

import React, { PureComponent } from 'react';

class SearchFlightBuilder extends PureComponent {

  scrollRef = React.createRef();

  state = {
    loading: true,
    error: false,
    filteredList: [],
    pageIndex: 0,
    scrollCalled: false,
  };


  handleScroll = (event) => {
    // make sure scroll should be called once
    if ((this.scrollRef.current.scrollTop + this.scrollRef.current.clientHeight >= this.scrollRef.current.scrollHeight) && !this.state.scrollCalled)  {
      this.setState({
          pageIndex: this.state.pageIndex + 1
      });
      this.setState({scrollCalled: true});
    }
  };

  componentDidMount = () => {
    this.scrollRef.current.addEventListener('scroll', this.handleScroll);
  };

  removeScrollEvent = () => {
    this.scrollRef.current.removeEventListener('scroll', this.handleScroll);
  };

  render() {

    return (
      <div className={c('Search-flight-builder')}  ref={this.scrollRef}>
        <p>Hello</P
      </div>
    );
  }
};

export default SearchFlightBuilder;

测试文件如下所示-

import React from 'react';
import { shallow, mount, render } from 'enzyme';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

import SearchFlightBuilder from './SearchFlightBuilder';

configure({ adapter: new Adapter() });

const testFlightBuilder = () => <SearchFlightBuilder />;

describe('SearchFlightBuilder', () => {
  it('should render correctly', () => {
    const component = shallow(<SearchFlightBuilder />);
    expect(component).toMatchSnapshot();
  });


});

运行测试时,出现此错误- TypeError: Cannot read property 'addEventListener' of null。我尝试了各种方法,但是没有一种方法有效。请在这里帮助我。我在这里使用酶库。

1 个答案:

答案 0 :(得分:0)

这是我的单元测试策略:

index.tsx

import React, { PureComponent } from 'react';

class SearchFlightBuilder extends PureComponent {
  scrollRef: any = React.createRef();

  state = {
    loading: true,
    error: false,
    filteredList: [],
    pageIndex: 0,
    scrollCalled: false
  };

  handleScroll = event => {
    // make sure scroll should be called once
    if (
      this.scrollRef.current.scrollTop + this.scrollRef.current.clientHeight >= this.scrollRef.current.scrollHeight &&
      !this.state.scrollCalled
    ) {
      this.setState({
        pageIndex: this.state.pageIndex + 1
      });
      this.setState({ scrollCalled: true });
    }
  };

  componentDidMount = () => {
    this.scrollRef.current.addEventListener('scroll', this.handleScroll);
  };

  removeScrollEvent = () => {
    this.scrollRef.current.removeEventListener('scroll', this.handleScroll);
  };

  render() {
    return (
      <div className="Search-flight-builder" ref={this.scrollRef}>
        <p>Hello</p>
      </div>
    );
  }
}

export default SearchFlightBuilder;

由于clientHeightscrollHeight属性是只读的,因此需要使用Object.defineProperty模拟它们。

index.spec.tsx

import React from 'react';
import { shallow } from 'enzyme';
import SearchFlightBuilder from './';

describe('SearchFlightBuilder', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  it('should handle scroll, pageindex + 1', () => {
    const mDiv = document.createElement('div');
    const events = {};
    const addEventListenerSpy = jest.spyOn(mDiv, 'addEventListener').mockImplementation((event, handler) => {
      events[event] = handler;
    });
    mDiv.scrollTop = 1;
    Object.defineProperty(mDiv, 'clientHeight', { value: 1 });
    Object.defineProperty(mDiv, 'scrollHeight', { value: 1 });
    const mRef = { current: mDiv };
    const createRefSpy = jest.spyOn(React, 'createRef').mockReturnValueOnce(mRef);
    const component = shallow(<SearchFlightBuilder />);
    expect(createRefSpy).toBeCalledTimes(1);
    expect(addEventListenerSpy).toBeCalledWith('scroll', component.instance()['handleScroll']);
    events['scroll']();
    expect(component.state('pageIndex')).toBe(1);
    expect(component.state('scrollCalled')).toBeTruthy();
  });
});

带有覆盖率报告的单元测试结果:

PASS  src/stackoverflow/57943619/index.spec.tsx (8.618s)
  SearchFlightBuilder
    ✓ should handle scroll, pageindex + 1 (15ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |    94.44 |    85.71 |       80 |    93.75 |                   |
 index.tsx |    94.44 |    85.71 |       80 |    93.75 |                32 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.916s

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