我想实现一个异步点击一些api并执行一些计算的函数。但是我想使用Promise(也是因为我认为为它们编写单元测试很容易)
这是我要编写的函数。
<FlatList
data={travels}
renderItem={(travel) =>{ console.log(travel.item)}}
//other properties
/>
现在的问题是如何进行测试和模拟?我的第一个测试是是否调用了所有api方法,但我已经为此感到困惑。
const CalcFactory = (someApi1, someApi2, someApi3) =>
async function calculation(params){
return new Promise((res, rej) =>{
const data1 = someApi1.getData() // getData is async
someApi2.getData((err, data) =>{
if(err)
rej(err);
else
res();
});
});
}
模拟看起来像这样:
const Calculator = CalcFactory(api1Mock, api2Mock, api3Mock);
if('should hit all external apis', () => {
return Calculator(somedada).then(()=>{
expect(api1Mock.getData).toHaveBeenCalledWith(someData);
expect(api2Mock.getData).toHaveBeenCalledWith(somedata);
});
});
但是,运行测试时我总是会超时。我也不太确定这是否是编写函数的好方法,但是我真的很想使用Promise。
答案 0 :(得分:1)
在一个地方有getData
,在另一个地方有someData
。考虑到诺言没有被拒绝,这不是问题。 Calculator(somedada)
的诺言未解决,因为someApi2.getData
被错误地模拟并导致未完成的诺言。
使用async
函数不使用await
返回承诺是一种反模式。这意味着要么无法从async
中受益,要么承诺构造器除了承诺非承诺API之外还包含过多内容。
如果合理使用async
,可以是:
async function calculation(params){
...
const data1 = someApi1.getData()
const data2 = await new Promise((res, rej) =>{
someApi2.getData((err, data) => {
if(err)
rej(err);
else
res();
});
});
...
}
在Node中,可以使用util.promisify
来实现错误优先的回调。
模拟的someApi2.getData
应该使用预期的回调:
const api2Mock = {
getData: jest.fn().mockImplementation(cb => cb(null, 'data'))
}
如果someApi2.getData
被多次使用,则应合理化它而不是每次都使用promise构造器。