如何使用Jest和新的React lazy 16.6 API测试快照

Alb*_*ivé 4 javascript unit-testing reactjs jestjs react-test-renderer

我必须使用新的React lazyAPI(16.6)导入组件.

import React, {PureComponent, lazy} from 'react';

const Component1 = lazy(() => import('./Component1'));
const Component2 = lazy(() => import('./Component2'));

class CustomComponent extends PureComponent {
  ...
  render() {

  return (
    <div>
      <Component1 />
      <Component2 />
    </div>
  );
 }
}
Run Code Online (Sandbox Code Playgroud)

在我的测试中,我正在做这个组件的快照.这是一个非常简单的测试:

import { create } from 'react-test-renderer';

const tree = await create(<CustomComponent />).toJSON();

expect(tree).toMatchSnapshot();
Run Code Online (Sandbox Code Playgroud)

在日志中,测试失败并显示以下错误:

A React component suspended while rendering, but no fallback UI was specified.

Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
Run Code Online (Sandbox Code Playgroud)

我是否必须在每个测试套件中包装<Suspense>...

it('should show the component', async () => {
  const component = await create(
    <React.Suspense fallback={<div>loading</div>}>
     <CustomComponent /> 
    </React.Suspense> 
  ); 
  const tree = component.toJSON(); 

  expect(tree).toMatchSnapshot(); 

};
Run Code Online (Sandbox Code Playgroud)

如果我这样做,我只在快照中看到fallback组件.

+ Array [ + <div> + loading + </div>, + ]
Run Code Online (Sandbox Code Playgroud)

那么,哪种方法最好呢?

Olu*_*ule 8

我是否必须在每个测试套件中包装<Suspense>

是的,该Suspense组件是懒惰加载子组件所必需的,特别是在延迟组件可用时提供后备和协调.

导出Component1和输入Component2,CustomComponent以便可以在测试中导入它们.

import React, {PureComponent, lazy} from 'react';

export const Component1 = lazy(() => import('./Component1'));
export const Component2 = lazy(() => import('./Component2'));

export default class CustomComponent extends PureComponent {
  //...
}
Run Code Online (Sandbox Code Playgroud)

请记住,延迟加载的组件是有希望的.在测试中导入它们,并等待它们解析,然后再检查快照是否匹配.

import { create } from 'react-test-renderer';
import React, {Suspense} from 'react';
import CustomComponent, {Component1, Component2} from './LazyComponent';

describe('CustomComponent', () => {
  it('rendered lazily', async()=> {
    const root = create(
      <Suspense fallback={<div>loading...</div>}>
        <CustomComponent/>
      </Suspense>
    );

    await Component1;
    await Component2;
    expect(root).toMatchSnapshot();
  })
})
Run Code Online (Sandbox Code Playgroud)

  • `lazy(()=&gt; import('./ Component1'))`返回一个React对象组件,因此用`await Component1`等待对象对我不起作用。它会立即解决,并且没有足够的时间来加载惰性组件。暂挂仍然呈现后备属性。相反,我能够`await import('./ Component1')`和`await import('./ Component2')`。我认为测试套件可能可以在“ react-test-renderer”之前解决导入组件的问题,但是我还没有遇到这种竞争情况。 (2认同)

Rec*_*nes 5

根据github 中的评论,您可以使用 Jest 模拟惰性组件以返回实际组件,尽管您需要将惰性语句移动并导出到它们自己的文件中才能正常工作。

// LazyComponent1.ts
import { lazy } from 'react';

export default lazy(() => import('./Component1'));
Run Code Online (Sandbox Code Playgroud)
// CustomComponent.tsx
import React, { PureComponent } from 'react';
import Component1 from './LazyComponent1';
import Component2 from './LazyComponent2';

class CustomComponent extends PureComponent {
  ...
  render() {

  return (
    <div>
      <Component1 />
      <Component2 />
    </div>
  );
 }
}
Run Code Online (Sandbox Code Playgroud)
// CustomComponent.spec.tsx
import React, { Suspense } from 'react';
import { create } from 'react-test-renderer';
import CustomComponent from './CustomComponent';

jest.mock('./LazyComponent1', () => require('./Component1'));
jest.mock('./LazyComponent2', () => require('./Component2'));

describe('CustomComponent', () => {
  it('should show the component', () => {
    const component = await create(
      <Suspense fallback={<div>loading</div>}>
       <CustomComponent /> 
      </Suspense> 
    ); 
    const tree = component.toJSON(); 

    expect(tree).toMatchSnapshot(); 
  });
});
Run Code Online (Sandbox Code Playgroud)