我必须使用新的React lazy
API(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>
);
}
}
在测试中,我正在制作此组件的快照。这是一个非常简单的测试:
import { create } from 'react-test-renderer';
const tree = await create(<CustomComponent />).toJSON();
expect(tree).toMatchSnapshot();
在日志中,测试失败并显示以下错误:
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.
我是否必须使用<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();
};
如果这样做,我只会在快照中看到fallback
组件。
+ Array [ + <div> + loading + </div>, + ]
那么,哪种方法最好呢?
答案 0 :(得分:6)
我是否必须使用<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 {
//...
}
请记住,延迟加载的组件类似于promise。 将它们导入测试中,然后等待它们解决,然后再检查快照是否匹配。
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();
})
})
答案 1 :(得分:2)
使用 Enzyme 和 mount 这对我有用。它不需要更改任何导出。
// wait for lazy components
await import('./Component1')
await import('./Component2')
jest.runOnlyPendingTimers()
wrapper.update()
感谢 Andrew Ferk's comment 接受的答案。
答案 2 :(得分:1)
我有一个类似的问题,我想对嵌套组件以及其中之一进行延迟加载进行快照测试。嵌套看起来像这样:
SalesContainer -> SalesAreaCard -> SalesCard -> AreaMap
SalesContainer
是最重要的组成部分。 AreaMap
组件由SalesCard
使用React lazy和Suspense进行延迟加载。对于大多数开发人员而言,测试在本地通过且快照中呈现了AreaMap
。但是在Jenkins CI中,测试始终失败,并且AreaMap
从未渲染。至少可以说是片状。
要使测试通过,我在测试中添加了魔幻线await testRenderer.getInstance().loadingPromise;
。这是一个测试示例:
import React from 'react';
import renderer from 'react-test-renderer';
import wait from 'waait';
import SalesContainer from './index';
describe('<SalesContainer />', () => {
it('should render correctly', async () => {
const testRenderer = renderer.create(
<SalesContainer />
);
await wait(0);
await testRenderer.getInstance().loadingPromise;
expect(testRenderer).toMatchSnapshot();
});
});
答案 3 :(得分:1)
根据此comment in github,尽管您需要将惰性语句移动并将其导出到自己的文件中才能起作用,但是您可以使用Jest模拟惰性组件来返回实际的组件。
// LazyComponent1.ts
import { lazy } from 'react';
export default lazy(() => import('./Component1'));
// 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>
);
}
}
// 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();
});
});