测试库 findBy* 查询仅适用于 async/await

Testing Library findBy* queries only working with async/await

根据文档,findBy 查询 return Promise。但似乎将这些查询与 Promise.prototype.catch() 一起使用在将它们与 async/await + try...catch 一起使用的情况下不起作用。

例如,'not found' 按预期在此处记录:

const { screen } = require('@testing-library/dom');

beforeAll(() => {
  document.body.innerHTML = `
    <header></header>
  `;
});

test('DOM', async () => {
  try {
    await screen.findByRole('aaaaa');
    console.log('found');
  } catch {
    console.log('not found');
  }
});

但是,此处未记录任何内容:

test('DOM', () => {
  screen.findByRole('aaaaa')
    .then(() => {
      console.log('found');
    })
    .catch(() => {
      console.log('not found');
    });
});

这有什么原因吗?

你的两个例子不等价。语句 screen.findByRole('aaaaa') 不在 Promise 中。将函数设置为异步会将函数包装在 Promise 中。然后,等同于 async await 的写法如下所示。

除了您处理“在 Promise 中抛出错误...”的要求之外,我还调整了代码以处理函数返回一种错误类型的情况。

    /// I added fake up implementations just for ilustration
    let screen={
      findByRole:
        ()=>new Promise((resolve, reject) => setTimeout(
          ()=>{reject(new Error('The error'))}
          ,2000
        ))
    }

    // You can comment above and uncomment to test different scenarios
    //let screen={findByRole:()=>new Error('The error')}
    //let screen={findByRole:()=>5}

    function test(desc, func)
    {
      func()
    }
    /////

    test('DOM', () => {
      new Promise(
        (resolve, reject) => {
          let result = screen.findByRole('aaaaa')
          result instanceof Error? reject(result):resolve(result)
        })
        .then(() => {
          console.log('found');
        })
        .catch((e) => {
          console.log('not found and capture error: ' + e.message);
        });
    });

您只需要 return Promise 以便您的测试框架(可能是 Jest)知道等待测试完成。否则 Jest 无法知道这个测试是异步的,隐含地使用 async 关键字 returns a Promise.

const { screen } = require('@testing-library/dom');

test('DOM', () => {
  return screen.findByRole('aaaaa')
    .then(() => {
      console.log('found');
    })
    .catch(() => {
      console.log('not found');
    });
});