模拟导入的懒惰React组件

时间:2019-09-11 13:24:24

标签: javascript reactjs sinon javascript-import react-suspense

这是我的懒惰组件:

const LazyBones = React.lazy(() => import('@graveyard/Bones')
  .then(module => ({default: module.BonesComponent}))
export default LazyBones

我正在这样导入它:

import Bones from './LazyBones'

export default () => (
<Suspense fallback={<p>Loading bones</p>}>
  <Bones />
</Suspense>
)

在我的测试中,我有这种东西:

import * as LazyBones from './LazyBones';

describe('<BoneYard />', function() {
  let Bones;
  let wrapper;
  beforeEach(function() {
    Bones = sinon.stub(LazyBones, 'default');
    Bones.returns(() => (<div />));
    wrapper = shallow(<BoneYard />);
  });
  afterEach(function() {
    Bones.restore();
  });

  it('renders bones', function() {
    console.log(wrapper)
    expect(wrapper.exists(Bones)).to.equal(true);
  })

})

我希望测试能够通过,console.log打印出来:

<Suspense fallback={{...}}>
  <Bones />
</Suspense>

但是我得到<Bones />而不是<lazy />,但它未通过测试。

如何模拟导入的Lazy React组件,以使我的简单测试通过?

3 个答案:

答案 0 :(得分:3)

我不确定这是否是您要寻找的答案,但这听起来像是问题的一部分nominal_features。根据{{​​3}},transform_df无法与shallow一起使用。

但是,shallow在尝试对惰性组件存根时也不起作用-如果您调试DOM输出(使用React.lazy),则可以看到mount在DOM中,但它是真实的(非存根)版本。

好消息:如果您只想检查console.log(wrapper.debug())是否存在,则根本不必模拟该组件!该测试通过:

Bones

如果由于其他原因需要模拟组件,Bones将允许您这样做,但这听起来像是您在尝试避免使用import { Bones } from "./Bones"; import BoneYard from "./app"; describe("<BoneYard />", function() { it("renders bones", function() { const wrapper = mount(<BoneYard />); console.log(wrapper.debug()); expect(wrapper.exists(Bones)).to.equal(true); wrapper.unmount(); }); }); this threadjest的上下文中讨论了其他一些选项(例如 This thread),也可以与jest一起使用。

答案 1 :(得分:1)

您不需要使用lazy()来解析.then(x => x.default)函数,React已经为您完成了。

React.lazy采用必须调用动态import()的函数。这必须返回一个Promise,该Promise解析为一个带有默认导出的模块,该模块包含一个React组件。 React code splitting

语法应类似于:

const LazyBones = React.lazy(() => import("./LazyBones"))

示例:

// LazyComponent.js
import React from 'react'

export default () => (
  <div>
    <h1>I'm Lazy</h1>
    <p>This component is Lazy</p>
  </div>
)

// App.js
import React, { lazy, Suspense } from 'react'
// This will import && resolve LazyComponent.js that located in same path
const LazyComponent = lazy(() => import('./LazyComponent'))

// The lazy component should be rendered inside a Suspense component
function App() {
  return (
    <div className="App">
      <Suspense fallback={<p>Loading...</p>}>
        <LazyComponent />
      </Suspense>
    </div>
  )
}

Edit react-lazy-component-test


关于测试,您可以按照create-react-app中默认提供的React测试示例进行更改,并对其进行一些更改。

创建一个名为LazyComponent.test.js的新文件并添加:

// LazyComponent.test.js
import React, { lazy, Suspense } from 'react'
import { render, screen } from '@testing-library/react'

const LazyComponent = lazy(() => import('./LazyComponent'))

test('renders lazy component', async () => {
  // Will render the lazy component
  render(
    <Suspense fallback={<p>Loading...</p>}>
      <LazyComponent />
    </Suspense>
  )
  // Match text inside it
  const textToMatch = await screen.findByText(/I'm Lazy/i)
  expect(textToMatch).toBeInTheDocument()
})

实时示例:点击浏览器标签旁边的测试标签。如果它不起作用,只需重新加载页面即可。

Edit react-lazy-component-testing

您可以在其react-testing-library网站上找到更多Docs复杂的示例。

答案 2 :(得分:-2)

要模拟您的惰性组件,首先想到的是将测试转换为异步并等待组件存在,例如:

import CustomComponent, { Bones } from './Components';

it('renders bones', async () => {
   const wrapper = mount(<Suspense fallback={<p>Loading...</p>}>
                       <CustomComponent />
                   </Suspense>

   await Bones;
   expect(wrapper.exists(Bones)).toBeTruthy();
}