异步 componentDidMount 时使用 React 的 Jest 和 Enzyme 进行测试

Posted

技术标签:

【中文标题】异步 componentDidMount 时使用 React 的 Jest 和 Enzyme 进行测试【英文标题】:Testing with React's Jest and Enzyme when async componentDidMount 【发布时间】:2018-08-31 09:03:29 【问题描述】: 反应:16.3.0-alpha.1 开玩笑:“22.3.0” 酶:3.3.0 打字稿:2.7.1

代码:

class Foo extends React.PureComponent<undefined,undefined>
   bar:number;
   async componentDidMount() 
     this.bar = 0;
     let echarts = await import('echarts'); // async import
     this.bar = 100;
   

测试:

describe('...', () => 
  test('...', async () => 
    const wrapper = shallow(<Foo/>);
    const instance = await wrapper.instance();
    expect(instance.bar).toBe(100);
  );
);

错误:

Expected value to be:
  100
Received:
  0

【问题讨论】:

【参考方案1】:

解决方案:

1:使用 async/await 语法。

2:使用挂载(不浅)。

3:等待异步组件生命周期。

例如:

    test(' ',async () => 
      const wrapper = mount(
         <Foo />
      );
      await wrapper.instance().componentDidMount();
    )

【讨论】:

这不是您在上面发布的问题中要检查的内容。我的回答是您问题的正确解决方案。 这会导致方法运行两次。 @VivekN 有正确的解决方案。这将运行“componentDidMount”两次。安装后的任何等待都可能“解决”问题,但我认为这不是正确的解决方案。【参考方案2】:

这样的东西应该适合你:-

 describe('...', () => 
   test('...', async () => 
     const wrapper = await mount(<Foo/>);
     expect(wrapper.instance().bar).toBe(100);
   );
 );

【讨论】:

这对我来说是最好的解决方案,特别是因为我不想浅装 确实;如果组件的didMount 中有setState,则需要在expect 之前添加wrapper.update();【参考方案3】:

试试这个:

it('should do something', async function() 
  const wrapper = shallow(<Foo />);
  await wrapper.instance().componentDidMount();
  app.update();
  expect(wrapper.instance().bar).toBe(100);
);

【讨论】:

在通过谷歌查看这个问题并尝试通过 mount 的酶实现异步 componentDidMount 之后。而且“挂载”方式不适合反应原生项目 - 我有很多错误。这个方法帮助了我。而且你不需要安装jsdom和使用mount。 “react”:“16.4.1”,“react-native”:“0.56.0”,“酶”:“^3.4.4”,“jest”:“23.5.0” 这里有什么应用? @Pavan 我认为wrapper.update() 是有意的。 --ref 顺便说一句,await 不会在那里做任何事情,除非你的 componentDidMount() 返回一个承诺【参考方案4】:

这里提供的解决方案都没有解决我的所有问题。最后我找到了https://medium.com/@lucksp_22012/jest-enzyme-react-testing-with-async-componentdidmount-7c4c99e77d2d,它解决了我的问题。

总结

function flushPromises() 
    return new Promise(resolve => setImmediate(resolve));


it('should do someting', async () => 
    const wrapper = await mount(<Foo/>);
    await flushPromises();

    expect(wrapper.instance().bar).toBe(100);
);

【讨论】:

【参考方案5】:

您的测试还需要实现异步、等待。 例如:

  it('should do something', async function() 
    const wrapper = shallow(<Foo />);
    const result = await wrapper.instance();
    expect(result.bar).toBe(100);
  );

【讨论】:

已编辑,执行实例时是否尝试过await?,await基本上是在promise上运行 如果你能分享你的完整测试 我不认为.instance() 会返回一个承诺,所以我认为await 在那里没有做任何事情。 TypeError: wrapper.instance(...).then is not a function

以上是关于异步 componentDidMount 时使用 React 的 Jest 和 Enzyme 进行测试的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 componentDidMount 中取消异步/ajax 请求

反应等待异步还是重新渲染?

ReactJs:如何在渲染之前等待 componentDidMount() 完成?

在 componentDidMount() 中获取地理位置并发送 Ajax 请求

回流如何监听异步操作完成

react请求接口数据是在componentDidMount 还是componentWillMount周期好