【问题标题】:How do test async components with Jest?如何使用 Jest 测试异步组件?
【发布时间】:2018-03-24 22:13:09
【问题描述】:

谁能告诉我在安装调用componendDidMount()的组件时如何开玩笑地等待一个模拟的承诺解决?

class Something extends React.Component {
    state = {
      res: null,
    };

    componentDidMount() {
        API.get().then(res => this.setState({ res }));
    }

    render() {
      if (!!this.state.res) return
      return <span>user: ${this.state.res.user}</span>;
    }
}

API.get() 在我的笑话测试中被嘲笑

data = [
  'user': 1,
  'name': 'bob'
];

function mockPromiseResolution(response) {
  return new Promise((resolve, reject) => {
    process.nextTick(
      resolve(response)
    );
  });
}

const API = {
    get: () => mockPromiseResolution(data),
};

然后是我的测试文件:

import { API } from 'api';
import { API as mockAPI } from '__mocks/api';

API.get = jest.fn().mockImplementation(mockAPI.get);

describe('Something Component', () => {
  it('renders after data loads', () => {
    const wrapper = mount(<Something />);
    expect(mountToJson(wrapper)).toMatchSnapshot();
    // here is where I dont know how to wait to do the expect until the mock promise does its nextTick and resolves
  });
});

问题是我 expect(mountToJson(wrapper)) 正在返回 null,因为 &lt;Something /&gt; 的模拟 api 调用和生命周期方法尚未通过。

【问题讨论】:

  • 如果它与 jasmine 一起运行,您可以使用 jasmine.clock().install(); jasmine.clock().tick(1) 进行“时间旅行”,这应该足以完成您的下一个滴答。测试结束后别忘了运行jasmin.clock().uninstall()否则时钟会静止
  • 很遗憾没有使用 jasmine,使用的是 jest expect 库
  • 玩笑似乎有类似的描述here

标签: reactjs testing jestjs


【解决方案1】:

作为一种解决方法,将其从异步转换为同步

jest.spyOn(Api, 'get').mockReturnValue({
  then: fn => fn('hello');
});

【讨论】:

    【解决方案2】:

    Jest 有模拟伪造time travelling,要在您的情况下使用它,我想您可以将代码更改为以下样式:

    import { API } from 'api';
    import { API as mockAPI } from '__mocks/api';
    
    API.get = jest.fn().mockImplementation(mockAPI.get);
    
    jest.useFakeTimers(); // this statement makes sure you use fake timers
    
    describe('Something Component', () => {
      it('renders after data loads', () => {
        const wrapper = mount(<Something />);
    
        // skip forward to a certain time
        jest.runTimersToTime(1);
    
        expect(mountToJson(wrapper)).toMatchSnapshot();
      });
    });
    

    除了jest.runTimersToTime(),您还可以使用jest.runAllTimers()

    【讨论】:

    • 所以这看起来很有希望,但不幸的是,正在写入的快照仍然是一个没有 UI (...) 的空快照,我尝试了 jest.runTimersToTime(1)jest.runAllTimers()
    • 你能检查一下你的api函数是否被调用了吗?您是否尝试过等待 1000 毫秒?
    • 有趣的是,我在render() 函数的顶部添加了console.error(this.state),并且状态正在更新,似乎expect 比较快照的语句运行得太快了?也许我需要jest.runTimersToTime(1).then(() =&gt; // expect snapshot)
    • 如果它是一个承诺,那么你不妨从it 中返回它,前提是开玩笑的设置也支持返回的承诺:)
    • 好的,我做了return new Promise((resolve, reject) =&gt; process.nextTick( () =&gt; resolve(expect(mountToJson(wrapper)).toMatchSnapshot()) )),它成功了!
    猜你喜欢
    • 2019-10-30
    • 2017-04-18
    • 1970-01-01
    • 2020-02-25
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2018-11-12
    • 2018-01-14
    相关资源
    最近更新 更多