单元测试嵌套异步函数时异步回调超时

时间:2020-06-11 17:57:24

标签: javascript unit-testing jestjs

我想实现一个异步点击一些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。

1 个答案:

答案 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构造器。