期待一个 Promise *not* 完成,在 Jest

Expecting a Promise *not* to complete, in Jest

我有以下需要测试是否没有发生。

虽然测试类似的东西可能值得讨论(等待多长时间才足够?),但我希望 Jest 中有更好的方法来集成测试超时。到目前为止,我还没有找到,但让我们从测试开始吧。

test ('User information is not distributed to a project where the user is not a member', async () => {

  // Write in 'userInfo' -> should NOT turn up in project 1.
  //
  await collection("userInfo").doc("xyz").set({ displayName: "blah", photoURL: "https://no-such.png" });

  // (firebase-jest-testing 0.0.3-beta.3)
  await expect( eventually("projects/1/userInfo/xyz", o => !!o, 800 /*ms*/) ).resolves.toBeUndefined();

  // ideally:
  //await expect(prom).not.toComplete;    // ..but with cancelling such a promise

}, 9999 /*ms*/ );

eventually returns 一个 Promise 我想检查一下:

Jest 提供 .resolves.rejects 但没有任何东西可以将两者结合起来。

  1. 我可以使用一些 Jest 扩展机制创建预期的 .not.toComplete 吗?
  2. 我可以创建一个“运行 就在测试超时之前”(能够使测试通过或失败)触发器吗?

我认为 2. 建议可能会派上用场,并且可以为此创建一个功能请求,但让我们看看它会收到什么评论..


编辑:JS Promise 无法从外部取消(但它们可以从内部超时),这更加复杂。

我最终用自定义匹配器解决了这个问题:

/*
* test-fns/matchers/timesOut.js
*
* Usage:
*   <<
*     expect(prom).timesOut(500);
*   <<
*/
import { expect } from '@jest/globals'

expect.extend({
  async timesOut(prom, ms) {   // (Promise of any, number) => { message: () => string, pass: boolean }

    // Wait for either 'prom' to complete, or a timeout.
    //
    const [resolved,error] = await Promise.race([ prom, timeoutMs(ms) ])
      .then(x => [x])
      .catch(err => [undefined,err] );

    const pass = (resolved === TIMED_OUT);

    return pass ? {
      message: () => `expected not to time out in ${ms}ms`,
      pass: true
    } : {
      message: () => `expected to time out in ${ms}ms, but ${ error ? `rejected with ${error}`:`resolved with ${resolved}` }`,
      pass: false
    }
  }
})

const timeoutMs = (ms) => new Promise((resolve) => { setTimeout(resolve, ms); })
  .then( _ => TIMED_OUT);

const TIMED_OUT = Symbol()

source

好的一面是,它可以添加到任何 Jest 项目中。

不足的是,需要单独提及延迟(并保证之前不会发生Jest的超时)。

使问题代码变为:

await expect( eventually("projects/1/userInfo/xyz") ).timesOut(300)

Firebase 用户注意事项:

如果 Firestore JS SDK 客户端侦听器仍处于活动状态,Jest 不会退出到 OS 级别。您可以通过在 afterAll 中取消订阅来阻止它 - 但这意味着要跟踪哪些听众还活着,哪些不活着。 firebase-jest-testing 库在幕后为您做这件事。此外,这最终会 ;) 由 Firebase 修复。