Jest can#39;t test an awaited promise, it times out instead(笑话不能测试期待的承诺,相反,它会超时。)
问题描述
我从只运行axios get切换到返回承诺,现在我的Jest测试失败了:
下载‘resource ce.js’中的压缩文件:
async function downloadMtgJsonZip() {
  const path = Path.resolve(__dirname, 'resources', fileName);
  const writer = Fs.createWriteStream(path);
  console.info('...connecting...');
  const { data, headers } = await axios({
    url,
    method: 'GET',
    responseType: 'stream',
  });
  return new Promise((resolve, reject) => {
    let error = null;
    const totalLength = headers['content-length'];
    const progressBar = getProgressBar(totalLength);
    console.info('...starting download...');
    data.on('data', (chunk) => progressBar.tick(chunk.length));
    data.pipe(writer);
    writer.on('error', (err) => {
      error = err;
      writer.close();
      reject(err);
    });
    writer.on('close', () => {
      const now = new Date();
      console.info(`Completed in ${(now.getTime() - progressBar.start) / 1000} seconds`);
      if (!error) resolve(true);
      // no need to call the reject here, as it will have been called in the
      // 'error' stream;
    });
  });
}
"resource ce.spec.js"中的以下测试现在均未通过:
it('fetches successfully data from an URL', async () => {
    const onFn = jest.fn();
    const data = { status: 200, data: { pipe: () => 'data', on: onFn }, headers: { 'content-length': 100 } };
    const writerOnFn = jest.fn();
    axios.mockImplementationOnce(() => data);
    fs.createWriteStream.mockImplementationOnce(() => ({ on: writerOnFn }));
    await downloadMtgJsonZip();
    expect(onFn).toHaveBeenCalledWith('data', expect.any(Function));
    expect(axios).toHaveBeenCalledWith(
      expect.objectContaining({ url: 'https://mtgjson.com/api/v5/AllPrintings.json.zip' }),
    );
    expect(axios).toHaveBeenCalledWith(
      expect.objectContaining({ responseType: 'stream' }),
    );
  });
  it('ticks up the progress bar', async () => {
    const tickFn = jest.fn();
    const dataOnFn = jest.fn((name, func) => func(['chunk']));
    const data = { status: 200, data: { pipe: () => 'data', on: dataOnFn }, headers: { 'content-length': 1 } };
    const writerOnFn = jest.fn();
    ProgressBar.mockImplementationOnce(() => ({ tick: tickFn }));
    axios.mockImplementationOnce(() => data);
    fs.createWriteStream.mockImplementationOnce(() => ({ on: writerOnFn }));
    await downloadMtgJsonZip();
    expect(ProgressBar).toHaveBeenCalledWith(
      expect.stringContaining('downloading'),
      expect.objectContaining({
        total: 1,
      }),
    );
    expect(tickFn).toHaveBeenCalledWith(1);
  });
});
值得注意的是,VSCode告诉我,对于‘resource ce.js’‘this expression is not call’中的axios,Nothing没有mockImplementationOnce(它‘在类型.上不存在’)。
以前我的downloadMtgJsonZip看起来是这样的:
async function downloadMtgJsonZip() {
  const path = Path.resolve(__dirname, 'resources', 'AllPrintings.json.zip');
  const writer = Fs.createWriteStream(path);
  console.info('...connecting...');
  const { data, headers } = await axios({
    url,
    method: 'GET',
    responseType: 'stream',
  });
  const totalLength = headers['content-length'];
  const progressBar = getProgressBar(totalLength);
  const timer = setInterval(() => {
    if (progressBar.complete) {
      const now = new Date();
      console.info(`Completed in ${(now.getTime() - progressBar.start) / 1000} seconds`);
      clearInterval(timer);
    }
  }, 100);
  console.info('...starting download...');
  data.on('data', (chunk) => progressBar.tick(chunk.length));
  data.pipe(writer);
}
测试中唯一不同的是createWriteStream的mock更简单(它显示为fs.createWriteStream.mockImplementationOnce(() => 'fs');)
我已尝试添加:
  afterEach(() => { 
    jest.clearAllMocks(); 
    jest.resetAllMocks();
  });
我已尝试添加writerOnFn('close');以尝试触发writer.on('close', ...)。
但我直到收到此错误:
:timeout-未在jest.setTimeout.Timeout指定的5000毫秒超时内调用异步回调-未在jest.setTimeout指定的5000毫秒超时内调用异步回调。错误:
我找不出丢失了什么,无法进行要"调用"的异步调用。last time I had this issue模仿createWriteStream解决了我的问题,但我看不到其他东西可以模仿?
如何使这些测试再次通过?
推荐答案
如何在测试代码中调用使用writer.on(event, handler)附加的事件处理程序?writerOnFn模拟不需要调用传入的处理程序函数吗?如果未调用这些函数,则resolve(true)永远不会被调用,因此对测试内部await downloadMtgJsonZip();的调用永远不会解析。
我认为您需要这样的东西
const writerOnFn = jest.fn((e, cb) => if (e === 'close') cb())
当然,您可能想要充实它以区分"error"和"Close"事件,或者如果您有关于"error"条件的测试,请确保更改它。
这篇关于笑话不能测试期待的承诺,相反,它会超时。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:笑话不能测试期待的承诺,相反,它会超时。
				
        
 
            
        - 如何显示带有换行符的文本标签? 2022-01-01
 - 如何向 ipc 渲染器发送添加回调 2022-01-01
 - 为什么我的页面无法在 Github 上加载? 2022-01-01
 - 在不使用循环的情况下查找数字数组中的一项 2022-01-01
 - 从原点悬停时触发 translateY() 2022-01-01
 - 我不能使用 json 使用 react 向我的 web api 发出 Post 请求 2022-01-01
 - 为什么悬停在委托事件处理程序中不起作用? 2022-01-01
 - 如何调试 CSS/Javascript 悬停问题 2022-01-01
 - 使用 iframe URL 的 jQuery UI 对话框 2022-01-01
 - 是否可以将标志传递给 Gulp 以使其以不同的方式 2022-01-01
 
						
						
						
						
						
				
				
				
				