简体   繁体   English

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

[英]Async callback timeout when unit testing nested async function

I want to implement a function which hits some apis asynchronously and does some calculations.我想实现一个 function 异步命中一些 api 并进行一些计算。 However I would like to use promises (also because I thought its easy to write unit test for them)但是我想使用承诺(也因为我认为为它们编写单元测试很容易)

This is the function I want to write.这是我要写的function。

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();
      });
    });
 }

The question now is how to test and mock this?现在的问题是如何测试和模拟这个? My first test is if all the api methods are beeing called but I already struggle with that.我的第一个测试是是否正在调用所有 api 方法,但我已经为此苦苦挣扎。

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);
   });

});

the mocks look like this:模拟看起来像这样:

const api1Mock = {
   someData: jest.fn(),
}

const api2Mock = {
someData: jest.fn().mockResolvedValue({
      data:{},
   })
}

However I always get a timeout when I run the test.但是,当我运行测试时,我总是会超时。 I am also not really sure if this is a good approach to write the function but I really would like to use a promise.我也不确定这是否是编写 function 的好方法,但我真的很想使用 promise。

There's getData in one place and someData in another.一个地方有getData ,另一个地方有someData Considering the promise is not rejected, it's not a problem.考虑到 promise 没有被拒绝,这不是问题。 Calculator(somedada) promise isn't resolved because someApi2.getData is incorrectly mocked and results in pending promise. Calculator(somedada) promise 未解决,因为someApi2.getData被错误地模拟并导致待处理的 promise。

It's an antipattern to return a promise from async function without using await .在不使用await的情况下从async function 返回 promise 是一种反模式。 This means that either it doesn't benefit from being async , or promise constructor contains too much besides promisfication of non-promise API.这意味着它要么不能从async中受益,要么 promise 构造函数除了承诺 API 之外包含太多内容。

In case the use of async is justified, it can be:如果使用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();
      });
  });
  ...
}

In Node, error-first callbacks can be promisified with util.promisify .在 Node 中,可以使用util.promisify对错误优先回调进行承诺。

And mocked someApi2.getData should use a callback like expected:并且嘲笑someApi2.getData应该使用像预期的回调:

const api2Mock = {
  getData: jest.fn().mockImplementation(cb => cb(null, 'data'))
}

If someApi2.getData is used more than once, it makes sense to promisify it instead of using promise constructor every time.如果someApi2.getData被多次使用,那么承诺它而不是每次都使用 promise 构造函数是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM