模拟React.Suspense,同时保留其余的React [英] Mocking out React.Suspense Whilst Leaving the Rest of React Intact
问题描述
我正在尝试为使用
I'm trying to write a Jest unit test for a component that uses React.Suspense.
正在测试的组件模块的简化版本:
Simplified versions of my component modules under test:
MyComponent.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>
);
天真的,我第一次尝试使用酶来安装挂起的组件的单元测试:
Naïvely, in my first attempt, I wrote a unit test that uses Enzyme to mount the suspended component:
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();
});
这会导致测试崩溃并显示错误消息:
This causes the test to crash with the error message:
错误:酶内部错误:标记为13的未知节点
Error: Enzyme Internal Error: unknown node with tag 13
在网络上搜索错误消息时,我发现这很可能是由于酶尚未准备好渲染Suspense
(尚未)造成的.
Searching for the error message on the web, I found that this is most likely caused by Enzyme not being ready to render Suspense
(yet).
如果我使用shallow
而不是mount
,则错误消息将更改为:
If I use shallow
instead of mount
, the error message changes to:
永久违反:ReactDOMServer尚不支持Suspense
Invariant Violation: ReactDOMServer does not yet support Suspense
我的下一个尝试是使用虚拟的直通组件来模拟Suspense
,如下所示:
My next attempt was to mock out Suspense
with a dummy pass-through component, like this:
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模块有一个模拟实现,其中包含React库中的所有实际代码,只有Suspense
被一个模拟函数代替.
The idea is to have a mock implementation of the React module that contains all the actual code from the React library, with only Suspense
being replaced by a mock function.
我已将此模式与requireActual
一起使用,如 Jest文档中所述,在模拟除React之外的其他模块时成功地在其他单元测试中使用,但是对于React,它不起作用.
I've used this pattern with requireActual
, as described in the Jest documentation, successfully in other unit tests when mocking other modules than React, but with React, it does not work.
我现在得到的错误是:
TypeError:((($ _ $ w(...), react)||($ $ w(...),_load_react(...))).default.createElement不是功能
TypeError: (($_$w(...) , react) || ($$w(...) , _load_react(...))).default.createElement is not a function
...我认为这是由于我的模拟技巧之后无法使用React的原始实现所致.
…which, I assume, is caused by the original implementation of React not being available after my mocking trick.
如何在保持React库其余部分不变的情况下模拟Suspense?
还是有另一种更好的方法来测试悬挂的组件?
Or is there another, better way to test suspended components?
推荐答案
解决方案不是使用对象扩展来导出原始的React模块,而是简单地覆盖Suspense
属性,如下所示:
The solution is not to use object spreading to export the original React module, but simply overwriting the Suspense
property, like this:
MySuspendedComponent.test.js
import React from 'react';
import { mount } from 'enzyme';
import MySuspendedComponent from './MySuspendedComponent';
jest.mock('react', () => {
const React = jest.requireActual('react');
React.Suspense = ({ children }) => children;
return React;
});
test('the suspended component renders correctly', () => {
const wrapper = mount(<MySuspendedComponent />);
expect(wrapper.html()).toMatchSnapshot();
});
这将按预期创建以下快照:
This creates the following snapshot, as expected:
MySuspendedComponent.test.js.snap
exports[`the suspended component renders correctly 1`] = `"<h1>Tadaa!!!</h1>"`;
这篇关于模拟React.Suspense,同时保留其余的React的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!