如何测试componentDidUpdate()?

时间:2018-10-22 14:29:13

标签: reactjs react-redux jestjs enzyme

这是示例实现:

export class Person extends Component {
  componentDidMount() {
    const { onLoadProfile, onLoadPolicy, person } = this.props
    onLoadProfile(person.profile.uri)
    onLoadPolicy(person.policy.uri)
  }

  componentDidUpdate(prevProps) {
    const { onLoadProfile, onLoadPolicy, person } = this.props
    const prevPerson = prevProps.person.uri
    const curPerson = person.uri

    // If person has changed, update Person component
    if (prevPerson !== curPerson) {
      onLoadProfile(person.profile.uri)
      onLoadPolicy(person.policy.uri)
    }
  }
}

componentDidMount()上,我设法像这样进行测试:

describe('<Person />', () => {
  let props
  let mountedPerson
  const mockLoadProfile = jest.fn()
  const mockLoadPolicy = jest.fn()

  const person = () => {
    if (!mountedPerson) {
      mountedPerson = mount(<Person {...props} />)
    } 
    return mountedPerson
  }

  beforeEach(() => {
    props = {
      onLoadProfile = mockLoadProfile,
      onLoadPolicy = mockLoadPolicy
    }
    mountedPerson = undefined
  })

  afterEach(() => {
    mockLoadProfile.mockClear()
    mockLoadPolicy.mockClear()
  })

  describe('componentDidMount', () => {
    it('loads profile', () => {
      person().instance().componentDidMount()
      expect(mockLoadProfile).toBeCalled()
    })

    it('loads policy', () => {
      person().instance().componentDidMount()
      expect(mockLoadPolicy).toBeCalled()
    })
  })
})

componentDidUpdate()上,我需要该组件尝试两次render()才能验证它是否应该在适当的时候更新,反之亦然,但是我找不到正确的方法来做吧。

在React中测试componentDidUpdate()方法的正确方法是什么?

PS 。:我正在使用玩笑反应15

2 个答案:

答案 0 :(得分:17)

我使用了不同的方法,但是您可以复制这个想法。您需要更改道具,我使用了setProps()函数:

describe('componentDidUpdate', () => {
    it('loads profile', () => { 
        const wrapper = shallow(<Person  {...props} />) as any;
        wrapper.setProps({ person: { uri: "something_different" } });
        expect(wrapper.instance().props.onLoadProfile).toBeCalled();
    })
})

运行测试后,我可以看到componentDidUpdate中覆盖测试页面中的粉红色消失了

答案 1 :(得分:3)

公认的答案是测试上述情况的最简单方法,但是您也可以考虑从以下组件中提取componentDidUpdate逻辑作为解决方案:

// Component definition
export class Person extends Component {
  componentDidUpdate(prevProps) {
    this.props.handleComponentDidUpdate(prevProps, this.currentProps)
  }
  // Rest of component
}

// Component functions/handlers testing
describe('Person component props', () => {
  describe('handleComponentDidUpdate', () => {
    it('loads profile & policy if person changes', () => {
      const onLoadPolicy = jest.fn()
      const onLoadProfile = jest.fn()
      const prevProps = {
        person: { uri: 'some-person-uri-old' },
        policy: { uri: 'some-policy-uri' },
        profile: { uri: 'some-profile-uri' },
        onLoadPolicy,
        onLoadProfile
      }
      const props = {
        person: { uri: 'some-person-uri-new' }, // person uri changes
        policy: { uri: 'some-policy-uri' },
        profile: { uri: 'some-profile-uri' },
        onLoadPolicy,
        onLoadProfile
      }

      handleComponentDidUpdate(prevProps, props)

      expect(onLoadPolicy).toHaveBeenCalled()
      expect(onLoadProfile).toHaveBeenCalled()
    })
  })
})

通过这种方式,组件可以尽可能地笨拙,并且可以将应用程序逻辑提取到更易于测试的函数/处理程序中。这样,您可以将测试更多地集中在功能上(更易于测试),而将重点放在组件上(更难于测试)。

关于使用Person组件,您只需提供所需的道具,包括handleComponentDidUpdate

如果仍然需要测试组件,则可以执行以下简单测试(请注意,在此测试中,与上面的功能/处理程序测试不同,我们不在乎应用程序的逻辑,例如人员,个人资料,策略等等):

// Component testing
describe('<Person/>', () => {
  it('should call handleComponentDidUpdate on prop change', () => {
    const handleComponentDidUpdate = jest.fn()
    const prevProps = {
      someProp: 'some-prop-prev',
      handleComponentDidUpdate
    }
    const newprops = {
      someProp: 'some-prop-new',
      handleComponentDidUpdate
    }

    const wrapper = shallow(<Person { ...prevProps } />)
    wrapper.setProps(newprops)

    expect(handleComponentDidUpdate).toHaveBeenCalledWith(prevProps, newProps)
  })
})