使用 React Suspense 和 React.lazy 子组件测试 Jest/Enzyme 类组件

IT技术 javascript reactjs testing jestjs enzyme
2021-05-24 03:08:59

所以我将类组件中使用的导入转换为 React.lazy import api 并将其包装在 Suspense 标签中。当我测试那个类组件时,酶会抛出一个错误"Enzyme Internal Error: unknown node with tag 13"有没有办法渲染和测试延迟加载组件的安装而不是使用浅渲染?

我已经尝试过 async await 等待延迟加载的Promise解决,但这也不起作用,如下所示:

it('async await mount', () async () => {
  const wrapper = await mount(<Component />)
}

这是示例代码:

组件.js

import React, { PureComponent, Suspense } from 'react'

const ChildComponent = React.lazy(() => import('../ChildComponent'))

export default class Component extends PureComponent {
  constructor() {
      super()
      this.state = {
          example: null
      }
  }

  doSomething = () => this.setState({
      example: 'example'
  })

  render() {
    return (
      <div>
        <p>Example</p>
        <Suspense fallback={<div>...loading</div>}>
            <ChildComponent 
               example={this.state.example}
               doSomething={this.doSomething}
            />
        </Suspense>
      </div>
    )
  }
}

组件.test.js

import React from 'react'
import renderer from 'react-test-renderer'
import { mount } from 'enzyme'
import Component from '../../Component'

describe('Component', () => {
    // snapshot renders loading and not children
    it('example snapshot of tree', () => {
        const tree = renderer.create(<Component />).toJSON()
        expect(tree).toMatchSnapshot()
    })

    it('example mount test', () => {
        // this test fails and throws error I state above
        const wrapper = mount(<Component />)
        wrapper.setState({ example: 'example' })
        expect(wrapper.state.example).toBe('example')
    })
})

我读到 Enzyme 尚不支持 React 16.6 Suspense API,但我想知道是否还有一种方法可以测试挂载,以便我可以使用Enzyme 中的 APIsimulatefindAPI 之类的东西

2个回答

解决方案

ChuckJHardy 链接的 GitHub 问题已解决合并发布。从 1.14.0 开始,您现在可以在酶中使用 mount API。

参考

https://github.com/airbnb/enzyme/pull/1975

我需要使用 Enzyme 测试我的惰性组件。以下方法对我有用,可以测试组件加载完成情况:

const myComponent = React.lazy(() => 
      import('@material-ui/icons')
      .then(module => ({ 
         default: module.KeyboardArrowRight 
      })
   )
);

测试代码 ->

//mock actual component inside suspense
jest.mock("@material-ui/icons", () => { 
    return {
        KeyboardArrowRight: () => "KeyboardArrowRight",
}
});

const lazyComponent = mount(<Suspense fallback={<div>Loading...</div>}>
           {<myComponent>}
       </Suspense>);
    
const componentToTestLoaded  = await componentToTest.type._result; // to get actual component in suspense
    
expect(componentToTestLoaded.text())`.toEqual("KeyboardArrowRight");

这是 hacky 但适用于酶库。