繁体   English   中英

在使用酶和玩笑对组件进行单元测试时,我们能否跳过反应挂钩(getpropivedstatefromprops)

[英]Can we skip a react hook (getderivedstatefromprops) while unit test of a component using Enzyme and jest

在使用酶和玩笑对组件进行单元测试时,我们可以跳过反应钩子(“ propderivedstatefromprops”)吗?

我正在编写一个Counter组件,其初始状态设置为零,并且从父组件接收到新状态,而在单元测试中模拟增量或减量功能时,由于“ getderivedstatefromprops”钩子,更改后的状态被父项初始状态覆盖。 在组件中,它仅被调用一次,但是在单元测试中,当我们在模拟增量函数后更新组件实例时,它会接收初始值并将状态更改为初始状态。 这在创建组件实例时有什么办法吗?

export default class Counter extends React.Component<CounterProps, 
   CounterState> {
     state = {
      value: 0,
     }

   static getDerivedStateFromProps(props, state)   {
      return { ...state, value: props.initialValue }     
   }

   incrementCounter = () => {
     const { value } = this.state

     const { id, maxValue, countChangeHandler, isDisabled } = this.props

       const newValue = value + 1

       if (newValue <= maxValue) {
         countChangeHandler(id, newValue) 
       }

      this.setState({ value: newValue })
  }

  render() {   

     const { value } = this.state
     const { maxValue, isDisabled } = this.props

    return (
      <StyledCounter>
        <Count disabled={isDisabled}>{value}</Count>
        <Action onClick={this.incrementCounter}>
          <Icon shape="plusGray" size="20px" />
        </Action>
        <Label>{'max ' + maxValue}</Label>
      </StyledCounter>
    )}

}

单元测试:

describe('Counter components', () => {
  function renderCounter(customProperties = {}) {
    const properties = { 

      id: 124355,

      initialValue: 3,

      maxValue: 5,

      isDisabled: false,

      countChangeHandler: jest.fn(),
      ...customProperties,
    }
    const { output } = renderComponent(<Counter {...properties} />)

    return output
  }

  afterEach(() => {
    jest.resetAllMocks()
  })

  it('On multiple click on Increment button, counter value should not exceed max value.', () => {
    const component = renderCounter()

    component.find('div#increment').simulate('click')
    component.find('div#increment').simulate('click')
    component.find('div#increment').simulate('click')
    component.find('Counter').update()
    expect(component.find(Counter).state('value')).toEqual(5)
  })  

})

renderComponent正在使用Mount。 单元测试未能达到预期的5,但收到了3。

因此,当组件本身不更新其某些状态并应依靠父级时,您的组件就像React中的controlled input模式。

我相信您不需要任何特殊技巧就可以对其进行测试。 我在这里测试的是:

  1. 更新props.value会影响render结果
  2. 单击按钮使用props.value + 1调用props.countChangeHandler ,而小于props.maxValue
  3. 点击按钮不叫props.countChangeHandler在所有如果它超过props.maxValue
const countChangeHandlerMocked = jest.fn();
function createCounter({ initialValue, maxValue }) {
  return shallow(<Counter 
    initialValue={initialValue} 
    maxValue={maxValue} 
    id="mock_id" 
    countChangeHandler={countChangeHandlerMocked} 
  />);
}

it('renders props.value as a Count`, () => {
  const wrapper = createCounter({initialValue: 42, maxValue: 100});
  expect(wrapper.find(Count).props().children).toEqual(42);
  expect(countChangeHandlerMocked).not.toHaveBeenCalled();
});

it('keeps Count in sync with props.value on update', () => {
  const wrapper = createCounter({initialValue: 42, maxValue: 100});
  wrapper.setProps({ initialValue: 43 });
  expect(wrapper.find(Count).props().children).toEqual(43);
  expect(countChangeHandlerMocked).not.toHaveBeenCalled();
});

it('reacts on button click if value< maxValue', () => { 
  const wrapper = createCounter({ initialValue: 1, maxValue: 10 });
  wrapper.find(Action).props().onClick();
  expect(countChangeHandlerMocked).toHaveBeenCalledWith('mocked_id', 2);
});

it('does not react on button click if value == maxValue', () => {
  const wrapper = createCount({ initialValue: 10, maxValue: 10 });
  wrapper.find(Action).props().onClick();
  expect(countChangeHandlerMocked).not.toHaveBeenCalled();
})

看,您越依赖state或生命周期方法等实现细节,测试就变得越脆弱。 像上面说的那样进行测试,很容易将组件重构为一个功能或多个功能的组合(只是也许我们需要使用mount()而不是shallow ),并且组件和测试都可以。 相反,过分地依赖实现细节会导致您的测试失败,即使在进行了合法更改之后(例如删除gDSFP并在render()使用props.initialValue而不是state.value )。

是否有意义?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM