我正在尝试为使用React.Suspense的组件编写Jest单元测试。
被测组件module的简化版本:
我的组件.js
import React from 'react';
export default () => <h1>Tadaa!!!</h1>;
MySuspendedComponent.js
import React, { Suspense } from 'react';
import MyComponent from './MyComponent';
export default () => (
<Suspense fallback={<div>Loading…</div>}>
<MyComponent />
</Suspense>
);
天真地,在我的第一次尝试中,我编写了一个使用Enzyme挂载挂起组件的单元测试:
MySuspendedComponent.test.js
import React from 'react';
import { mount } from 'enzyme';
import MySuspendedComponent from './MySuspendedComponent';
test('the suspended component renders correctly', () => {
const wrapper = mount(<MySuspendedComponent />);
expect(wrapper.html()).toMatchSnapshot();
});
这会导致测试崩溃并显示错误消息:
错误:酶内部错误:标签为 13 的未知节点
在网上搜索错误信息,我发现这很可能是由于 Enzyme 尚未准备好渲染Suspense(尚未准备好)引起的。
如果我使用shallow而不是mount,则错误消息将更改为:
不变性违规:ReactDOMServer 尚不支持 Suspense
我的下一次尝试是Suspense用一个虚拟的 pass-through 组件来模拟,如下所示:
MySuspendedComponent.test.js
import React from 'react';
import { mount } from 'enzyme';
import MySuspendedComponent from './MySuspendedComponent';
jest.mock('react', () => {
const react = require.requireActual('react');
return () => ({
...react,
Suspense({ children }) {
return children;
}
});
});
test('the suspended component renders correctly', () => {
const wrapper = mount(<MySuspendedComponent />);
expect(wrapper.html()).toMatchSnapshot();
});
这个想法是有一个 React module的模拟实现,它包含来自 React 库的所有实际代码,只Suspense被一个模拟函数替换。
我已经在其他单元测试中成功使用了这种模式requireActual,如Jest 文档中所述,在模拟除 React 之外的其他module时,成功地用于其他单元测试,但是对于 React,它不起作用。
我现在得到的错误是:
TypeError: (($_$w(...) , react) || ($ $w(...) , _load_react(...))).default.createElement 不是函数
...我认为这是由于在我的嘲讽技巧之后 React 的原始实现不可用造成的。
如何在保持 React 库的其余部分完好无损的同时模拟 Suspense?
或者还有另一种更好的方法来测试悬挂的组件吗?