【问题标题】:Unable to reach 100% branch coverage in JEST + ENZYME在 JEST + ENZYME 中无法达到 100% 的分支覆盖率
【发布时间】:2018-01-15 07:28:03
【问题描述】:

我的 LoadingIndicator 测试文件中有以下代码。我正在使用 JEST + Enzyme 来测试 LoadingIndicator 容器类。

我一直在努力将分支覆盖率提高到 100%。它卡在 91% 上。我无法涵盖的分支是 LoadingIndicator 容器类中的 if (!this.timeoutID)。请帮助我了解我在这里缺少什么。

import ...;

import ConnectedLoadingIndicator,{ LoadingIndicator } from './loadingIndicator';

jest.useFakeTimers();

describe('LoadingIndicator unconnected container component', () => {

  let wrapper;
  let instance;
  beforeEach(() => {

                    wrapper = shallow(<LoadingIndicator
                                        loading='true'
                                        error='false' />);

                    instance = wrapper.instance();
                  });

  it('checks loadingIndicator is hidden on loading false', () => {
    wrapper.setProps({ loading: false, error: false });
    expect(instance.state.showIndicator).toBe(false);
    expect(wrapper.find('.loading-hidden').length).toEqual(1);
  });

  it('checks loadingIndicator is shown after timer runs', () => {
    wrapper.setProps({ loading: true, error: false });
    jest.runOnlyPendingTimers();
    expect(instance.state.showIndicator).toBe(true);
    expect(wrapper.find('.loading-show').length).toEqual(1);
  });

  it('checks loadingIndicator is hidden on error true', () => {
    wrapper.setProps({ loading: true, error: true });
    expect(instance.state.showIndicator).toBe(false);
    expect(wrapper.find('.loading-hidden').length).toEqual(1);
  });

  it('checks destroyTimer behavior on loading false and error false', () => {
    wrapper.setProps({ loading: false, error: false });
    expect(instance.timeoutID).toBe(null);
    expect(instance.state.showIndicator).toBe(false);
  });

});

LoadingIndicator 容器类

import ...;

import LoadingIndicatorComponent from '../../../../components/loadingIndicator';

export class LoadingIndicator extends Component {

  constructor(props) {
    super(props);
    this.timeoutID = null;
    this.state = {
      showIndicator: false,
    };
  }

  componentDidMount() {
    this.ensureTimer(this.props);
  }

  componentWillUnmount() {
    this.destroyTimer();
  }

  componentWillReceiveProps(props) {
    if (props.loading !== this.props.loading
          || props.error !== this.props.error) {
      this.ensureTimer(props);
    }
  }

  ensureTimer(props) {
    if (props.loading && !props.error) {
      if (!this.timeoutID) {
        this.timeoutID = setTimeout(() => {
          this.timeoutID = null;
          this.setState({ showIndicator: true });
        }, props.timeoutPeriod);
      }
    } else {
      this.destroyTimer();
    }
  }

  destroyTimer() {
    clearTimeout(this.timeoutID);
    this.timeoutID = null;
    this.setState({ showIndicator: false });
  }

  render() {
    console.log(this.state.showIndicator);
    return (
      <div className =
        {`${this.state.showIndicator ? 'loading-show' : 'loading-hidden'}`}>
        <LoadingIndicatorComponent>
          Loading...
        </LoadingIndicatorComponent>
      </div>
    );
  }

}

const mapStateToProps = (state) => ({
  loading: isLoading(state),
  error: hasError(state),
});

// timeoutPeriod of 1000 is for showing loading indicator after 1000ms
LoadingIndicator.defaultProps = {
  timeoutPeriod: 1000,
};

export default connect(mapStateToProps)(LoadingIndicator);

【问题讨论】:

    标签: javascript reactjs react-redux jestjs enzyme


    【解决方案1】:

    我已经更新了我的测试文件,如下所示。我发现两个分支都必须在一个测试中覆盖,而不是在单独的测试中。如果已经设置解决了覆盖问题,则检查 timeoutID 保持不变。

    import ...;
    
    import ConnectedLoadingIndicator,{ LoadingIndicator } from './loadingIndicator';
    
    jest.useFakeTimers();
    
    describe('LoadingIndicator unconnected container component', () => {
    
      let wrapper;
      let spy;
      let spyEnsureTimer;
      let instance;
      let props = {
        pendingRequest: 0
      }
      beforeEach(() => {
                        wrapper = shallow(<LoadingIndicator {...props} />,
                                            { lifecycleExperimental: true, });
    
                        instance = wrapper.instance();
                        spy = jest.spyOn(instance, 'componentWillReceiveProps');
                        spyEnsureTimer = jest.spyOn(instance, 'ensureTimer');
                      });
    
      it('renders', () => {
        expect(wrapper.length).toEqual(1);
      });
    
      it('checks for timeoutID remains unchanged if already set', () => {
          instance.ensureTimer(props);
          expect(instance.timeoutID).toBe(0);
          instance.ensureTimer({ pendingRequest: 1 });
          expect(instance.timeoutID).toBe(1);
          instance.ensureTimer({ pendingRequest: 1 });
          expect(instance.timeoutID).toBe(1);
      });
    
      it('checks componentWillReceiveProps and ensureTimer is called', () => {
        expect(spy).not.toHaveBeenCalled();
        wrapper.setProps({ pendingRequest: 1 });
        expect(spy).toHaveBeenCalled();
        expect(spyEnsureTimer.mock.calls.length).toBe(1);
      });
    
      it('checks ensureTimer is not called with same props', () => {
        expect(spyEnsureTimer.mock.calls.length).toBe(0);
        wrapper.setProps({ pendingRequest: 0 });
        expect(spyEnsureTimer.mock.calls.length).toBe(0);
      });
    
      it('checks loadingIndicator is shown on pendingRequest more than 0', () => {
        wrapper.setProps({ pendingRequest: 1 });
        jest.runOnlyPendingTimers();
        expect(instance.state.showIndicator).toBe(true);
        expect(wrapper.find('.loading-show').length).toEqual(1);
      });
    
      it('checks destroyTimer behavior on pendingRequest less than 1', () => {
        wrapper.setProps({ pendingRequest: 1 });
        jest.runOnlyPendingTimers();
        expect(instance.state.showIndicator).toBe(true);
        wrapper.setProps({ pendingRequest: 0 });
        expect(instance.timeoutID).toBe(0);
        expect(instance.state.showIndicator).toBe(false);
        expect(wrapper.find('.loading-hidden').length).toEqual(1);
      });
    
    });
    

    我已经修改了 LoadingIndicator 容器类以及以下内容:

    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    
    import { selectPendingRequest } from './selectors';
    import LoadingIndicatorComponent from '../../../../components/loadingIndicator';
    import './loadingIndicator.css';
    
    export class LoadingIndicator extends Component {
    
      constructor(props) {
        super(props);
        this.timeoutID = 0;
        this.state = {
          showIndicator: false,
        };
      }
    
      componentDidMount() {
        this.ensureTimer(this.props);
      }
    
      componentWillUnmount() {
        this.destroyTimer();
      }
    
      componentWillReceiveProps(props) {
        if (props.pendingRequest !== this.props.pendingRequest) {
          this.ensureTimer(props);
        }
      }
    
      ensureTimer(props) {
        if (props.pendingRequest > 0) {
          if (this.timeoutID === 0) {
            this.timeoutID = setTimeout(() => {
              this.timeoutID = 0;
              this.setState({ showIndicator: true });
            }, props.timeoutPeriod);
          }
        } else {
          this.destroyTimer();
        }
      }
    
      destroyTimer() {
        clearTimeout(this.timeoutID);
        this.timeoutID = 0;
        this.setState({ showIndicator: false });
      }
    
      render() {
        return (
          <div className =
            {`${this.state.showIndicator ? 'loading-show' : 'loading-hidden'}`}>
            <LoadingIndicatorComponent>
              Loading...
            </LoadingIndicatorComponent>
          </div>
        );
      }
    
    }
    
    const mapStateToProps = (state) => ({
      pendingRequest: selectPendingRequest(state) //count of pendingRequest
    });
    
    LoadingIndicator.defaultProps = {
      timeoutPeriod: 1000,
    };
    
    export default connect(mapStateToProps)(LoadingIndicator);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-11
      • 2019-04-08
      • 1970-01-01
      • 2016-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多