【问题标题】:Ava testing image-loading with promise: promise returned by test never resolvedAva 测试图像加载与承诺:测试返回的承诺从未解决
【发布时间】:2018-02-17 10:55:19
【问题描述】:

我想测试我的 promise 函数来加载一张图片,这段代码如下所示:

function imagePromise() {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.addEventListener('load', () => resolve(true));
    img.addEventListener('error', () => reject(false));
    img.src = 'http://78.media.tumblr.com/tumblr_lr9mx5Axur1qlyuwso1_1280.jpg';
  });
}

当我在浏览器中使用我的承诺时,它工作正常:

imagePromise().then((result) => console.log(result));
// fulfill the promise and log the result: true

但是,当我使用 avabrowser-env 测试我的承诺时,ava 返回错误:

Promise returned by test never resolved

我的测试文件如下所示:

import test from 'ava';

function imagePromise() {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.addEventListener('load', () => resolve(true));
    img.addEventListener('error', () => reject(false));
    img.src = 'http://78.media.tumblr.com/tumblr_lr9mx5Axur1qlyuwso1_1280.jpg';
  });
}

test('load image with promise', (t) => {
  return imagePromise().then((result) => {
    t.is(result, true);
  });
});

请注意,由于浏览器兼容性,我都尝试过 addEventListeneronload/onerror 方法,并且 browser-env 一直是 configured to work with ava。我有什么遗漏吗?

【问题讨论】:

    标签: javascript unit-testing ava


    【解决方案1】:

    我终于修复了我的测试,使用browser-env(它本身使用jsdom)。我做了一个small repo for people interested:

    我的第一个错误是我忘记安装canvas-prebuilt,它允许jsdom 操作imagescanvas 元素。

    // install browser-env and canvas-prebuilt
    // (https://github.com/jsdom/jsdom#loading-subresources)
    yarn add browser-env canvas-prebuilt -D
    

    我的第二个错误是我忘记在 test/helpers/setup-browser-env.js 文件中的 browser-env 声明中为测试添加一个特殊配置:

    require('browser-env')(['window', 'document', 'Image'], {
      resources: 'usable',
    });
    

    然后我们可以从test/test.js 运行我们的图像加载承诺测试:

    import test from 'ava';
    
    function imagePromise() {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.addEventListener('load', () => resolve(true));
        img.addEventListener('error', () => reject(false));
        // an heavy 4k wallpaper to check if promise is resolved after a long time
        img.src = 'https://www.wallpaperup.com/wallpaper/download/991808/8000/5224';
      });
    }
    
    test('load image with promise', (t) => {
      return imagePromise().then((result) => {
        t.is(result, true);
      });
    });
    

    要运行测试,您可以执行 ava,但我强烈建议添加 --verbose 标志,因为它有助于使用 --watch 标志进行调试(一种实时重新加载测试)。

    【讨论】:

      【解决方案2】:

      将图像创建从imagePromise 移动到ImageClass 怎么样?之后,您将可以控制承诺解决/拒绝

      import test from "ava";
      import { EventEmitter } from "events";
      
      function imagePromise(img) {
          return new Promise((resolve, reject) => {
              img.addEventListener("load", () => resolve(true));
              img.addEventListener("error", () => reject(false));
              img.src = "http://78.media.tumblr.com/tumblr_lr9mx5Axur1qlyuwso1_1280.jpg";
          });
      }
      
      test("load image with promise", t => {
          class ImageClass extends EventEmitter {
              addEventListener(type, fn) {
                  this.on(type, fn);
              }
          }
      
          const image = new ImageClass();
      
          process.nextTick(() => image.emit("load"));
      
          return imagePromise(image).then(result => {
              t.is(result, true);
          });
      });
      

      【讨论】:

      • 我已经做了一个粗略的例子来说明我想如何做事,但在这之后我有一个带有子加载器类的加载器类(例如 ImageLoader、AudioLoader、...)。但我终于设法修复了我的测试,我将在几分钟内将其写为答案。感谢您的帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-30
      • 2020-10-21
      • 2016-07-20
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      相关资源
      最近更新 更多