如何使用spyOn测试异步功能? [英] How to test async function with 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
无法读取未定义的属性"callThrough"
Cannot read property 'callThrough' of undefined
推荐答案
解决方案之一是进行测试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测试异步功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!