本文介绍了如何使用spyOn测试异步功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在React Native应用中测试异步功能.

I am trying to test an async function in a react native app.

class myClass extends React.Component {

  ...

  closeModal = async () => {

    if (someCondition) {
      await myFunction1();
    } else {
      await myFunction2();
    }

    this.props.navigation.state.params.onGoBack();
    this.props.navigation.navigate('Main');
  };

  ...

}

这是我的测试

const navigation = {
  navigate: jest.fn(),
  state: { params: { onGoBack: jest.fn() } },
};

const renderComponent = overrides => {
  props = {
    navigation,
    ...overrides,
  };

  return shallow(< myClass.wrappedComponent {...props} />);
};


describe('When the user presses the close icon', () => {
    it('should close the modal', () => {
      const wrapper = renderComponent();
      const instance = wrapper.instance();
      const spyCloseModal = jest.spyOn(instance, 'closeModal');
      instance().forceUpdate();
      component
        .find({ testID: 'close-icon' })
        .props()
        .onPress();
      expect(spyCloseModal).toHaveBeenCalled(); // this is passed
      expect(navigation.navigate).toHaveBeenCalled(); // this is not passed
    });
});

似乎卡在了await调用中.如果我删除了等待呼叫,那么它将过去.有人在另一篇文章中提到在spyOn之后使用.and.callThrough,但它给了我这个错误

It looks like it gets stuck on the await calls. If I remove the await calls then it passes. Someone mentioned in another post to use .and.callThrough after spyOn but it gives me this error

推荐答案

解决方案之一是进行测试async并运行await (anything)将测试拆分为多个微任务:

one of solution is to make your test async and run await (anything) to split your test into several microtasks:

it('should close the modal', async () => {
      const wrapper = renderComponent();
      component
        .find({ testID: 'close-icon' })
        .props()
        .onPress();
      await Promise.resolve();
      expect(navigation.state.params.onGoBack).toHaveBeenCalled(); 
      expect(navigation.navigate).toHaveBeenCalledWith("Main");
    });

我相信您不需要实例方法上的.forceUpdate.spyOn.导航正确完成后,无论调用哪种内部方法都无关紧要

I believe you don't need either .forceUpdate nor .spyOn on instance method. once navigation happens properly it does not matter by what internal method it has been called

有关微任务与宏任务的更多信息: https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f

more on microtask vs macrotask: https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f

替代方法是使用macrotask(setTimeout(...., 0))

alternative is to use macrotask(setTimeout(...., 0))

it('should close the modal', (done) => {
      const wrapper = renderComponent();
      component
        .find({ testID: 'close-icon' })
        .props()
        .onPress();
      setTimeout(() => {
        expect(navigation.state.params.onGoBack).toHaveBeenCalled(); 
        expect(navigation.navigate).toHaveBeenCalledWith("Main");
        done();
    });
}

这篇关于如何使用spyOn测试异步功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 21:42