首页 > 解决方案 > 如何在 react-testing-library 中测试第三方组件库

问题描述

我有一个 react 组件,它从另一个第三方库(例如:Ant 或 bootstrap )导入一个组件,现在我想测试这个组件的 onClick 行为。

但是,getByTestId 或 getByText 很难,因为第三方库没有 thiese 属性,或者有时 html 标签中没有文本。如何获取第三方 dom 并使用 react-testing-library 对其进行测试?

PS:有人可能会说,我们不必测试引导组件,因为这是他们的业务,但这会降低我们的测试覆盖率。(例如:如果我们将许多回调函数道具作为事件处理程序传递给引导组件,我们必须测试回调增加测试覆盖率)

标签: reactjsreact-testing-library

解决方案


据我了解,React 测试库的开发是为了根据用户对正在呈现的元素的体验编写测试。对于第三方组件,这有时会很麻烦。

我认为有几种方法可以采取:

  1. 查看 React 测试库备忘单,问问自己用户理解元素的主要方式。也许在这种情况下它是由元素的作用?即,您的第三方组件是否拥有指示该组件角色的 aria 属性?

示例:应用程序使用引导程序中的按钮

const App = () => {
  const [state, setState] = useState(0)

  const increase = () => {
    const newState = state + 1
    setState(newState)
  }

  const decrease = () => {
    const newState = state - 1
    setState(newState)
  }

  return (
  <div>
    <div className="App">
      <Button variant="primary" size="lg" onClick={increase}></Button>{' '}
      <Button variant="primary" size="lg" onClick={decrease}></Button>{' '}
    </div>
    <div className="number">
      {state}
    </div>
</div>
  )
}

我故意没有为按钮提供文本,但我仍然可以找到这些按钮,这是测试:

it('buttons increase and decrease displayed value', () => {
     const component = render(<App/>)
     const buttons = component.getAllByRole('button')

    for (let i = 0; i < buttons.length; i++){
      fireEvent.click(buttons[i])
    }

    expect(component.findByText('0')).toBeTruthy()
})

即使我无法设置 testId 或通过文本查找,我仍然可以收集起按钮作用的节点数组。从那里开始搜索数组以找到您需要的按钮。令我高兴的是,测试通过了,但这是一个愚蠢的测试,因为按钮有自己的逻辑,所以我应该将它们分成单独的测试:

it('increases and decreases button and displays accurate value', () => {
    const component = render(<App/>)
    const buttons = component.getAllByRole('button')

    fireEvent.click(buttons[0])

    expect(component.findByText('1')).toBeTruthy()
})
  1. 如果需要考虑将第三方组件包装在一个 div 中,为该数据提供一个 data-testid,然后访问该 div 的第一个、同级、最后一个子节点。我经常使用它来导航到 dom 中存在第三方组件节点的位置:

    <div data-testid="test">
        <SomeComponent onChange={()=> {}}/>
    </div>
    

由于一些反应测试库查询返回一个 dom 节点,我们可以通过以下方式找到该组件:

const findBootstrapComp = component.getByTestId('test').firstChild
  1. 我们可能应该尽可能避免,但考虑到可以通过提供的查询访问的内容,您的情况可能是允许的,您可以通过某些属性手动查询容器节点:

    const { container } = render()
    const button = container.querySelector('button')
    

长话短说,React 测试库提供了大量工具来查询您需要的内容。如果该第三方组件正在呈现,那么您可能可以查询该元素的属性。以上只是个人经验,每个项目都不一样。甚至可以考虑拉出那些回调,隔离它们然后测试逻辑,因为你更关心它的声音中的逻辑。

另外,我同意您对 Boostrap 测试自己的组件的看法。但是,您实际上并不是要测试第三方组件,而是要测试您编写的某些功能或逻辑,这些功能或逻辑正在被第三方组件访问。或者,也许您想提取该元素的 css 并确认它在开发过程中的某个时刻没有切换。不管是什么,我希望上面的内容能在某种程度上有所帮助。如果有的话,请使用第三方组件在测试文件中创建一个组件,并使用 debug() api 查看元素以查看您可能查询的内容。

有用的网址:

React 测试库备忘单

DOM 导航

节点接口


推荐阅读