【问题标题】:How to chain promises with multiple expections in jest如何在玩笑中链接具有多个异常的承诺
【发布时间】:2020-07-31 00:02:54
【问题描述】:

我正在尝试找到一种干净的方法来编写集成测试(使用真实资源的 jest 的单元测试)和 jest,使用 Promise 链接,但我可以理解它。

除了正确嵌套承诺之外,我也不知道如何解决这两个问题:

  • 如何在不同的 Promise 中有不同的 expects 被 jest 正确拾取
  • 即使有异常,也总是在清理资源的情况下进行拆解

我想链接 4 个函数,类似于 Act - Arrange - Assert 模式。 问题是这些功能对 f.e. 有异步调用。一个数据库,可以有期望。

为了更好地理解这里是一些伪代码,这在我的脑海中是如何看待的。这只应该提供对问题的更好理解。

const setupResources =  () =>  new Promise(resolve => {
  //async calls to a database to setup a test
  await dynamoDBClient.put(params).promise();
  // returns data which are necessary for the other steps
  resolve(data);
});

const act = (data) => new Promise(resolve => {
  // doing some stuff
  const otherdata = {data};
    // calling some endpoint asyc
   const result = await axios.post(
              `https://restapi.com/test`,
              JSON.stringify(otherdata),
          );
  // some expects
  expect(result.status).toBe(200);  

  // again some data which will be needed in the other steps
  resolve({someInformation: 'info', data}) ;
});

const assertIt = (data) => {
  const prarams = {/*db related data*/}
  new Promise(resolve=>{
      const dbdata = await dynamoDBClient.get(params).promise();

      // some expectation
      expect(dbdata).toBe(data.data);
      resolve();
 })

};

const tearDown = (data) => {
  // cleanup of data base trash which should always happen
  await dynamoDBClient.delete(data.params).promise();
};

如果有意义的话,实际测试应该看起来像这样。

it('test',()=>{
return setupResources()
        .then(act(data))
        .then(assertIt(data))
        .finally(teardown(data));
})

【问题讨论】:

    标签: unit-testing jestjs es6-promise


    【解决方案1】:

    async..await 是原始承诺的替代品,无需使用then。将new Promise 与现有承诺一起使用是一种反模式。 async 函数解决的问题之一是,需要在 Promise 链下可用的数据不需要通过整个链传递,它可以声明为链可用范围内的变量。

    应该是:

    const setupResources = async () => {
      await dynamoDBClient.put(params).promise();
      ...
      return data;
    });
    

    还有测试:

    it('test', async ()=> {
      let data;
    
      try {
        data = await setupResources();
        ...
       } finally {
         await teardown(data);
       }
    });
    

    设置和拆卸是beforeEachafterEach 块解决的任务。如果需要将它们提取为可重用函数,可以通过上下文对象共享公共数据,如 here 所示。

    【讨论】:

    • 这是一个更好的方法。
    • 谢谢。希望这有助于 OP 的案例。
    • 我现在用 async await 实现了它。它看起来不太好,但它更具可读性谢谢。
    【解决方案2】:

    看起来您需要一个异步测试,为此您可以编写以下代码。现在测试将等待(默认为 5 秒),直到一切都完成并符合预期。

    
    it('test', (done) => { // note the "done" argument
    return setupResources()
            .then(act(data))
            .then(assertIt(data))
            .finally(() => { teardown(data); done() });
    })
    
    

    【讨论】:

    • 好的,这样就解决了最后会有拆解的问题对吧?但是如何将函数中的数据从异步调用(这也是一个承诺)传递给下一个函数?
    • 在 Jest 中使用 done with promises 是一种反模式。这通常会导致额外的错误,因为它需要更多的关注。在这种特定情况下,done() 会导致测试通过,即使出现错误。
    • 是的,我认为这可以做得更好,因为断言是在 Promise 中完成的,所以从技术上讲,这个测试根本没有断言,为了让它正常工作,断言需要在这个测试中发生.使用 async await 语法会更容易理解,在这种情况下,我们也不需要使用 done
    • @ziZimon,如果您正在运行 Jest,您可以使用 async await 语法来编写它吗?它适用于 Promise,因为它实际上只是它的语法糖。如果你这样做,从另一个结果传递一个结果会容易得多,并且还可以获得等待一切完成的测试用例的奖励。
    • 所以我可以传递应该预期到最后的数据并在那里完成所有expects?但是如何在 promise 中调用异步数据库请求,该请求需要将结果数据传递给下一个带有附加数据的请求。
    猜你喜欢
    • 2018-12-10
    • 2018-11-19
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多