模拟React.Suspense,同时保留其余的React [英] Mocking out React.Suspense Whilst Leaving the Rest of React Intact

查看:510
本文介绍了模拟React.Suspense,同时保留其余的React的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为使用 Jest 单元测试. /reactjs.org/docs/code-splitting.html#suspense"rel =" nofollow noreferrer> React.Suspense .

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆