【问题标题】:Use of tick() after nested promise doesn't cause waiting for promises to finish (Karma/Jasmine)在嵌套承诺后使用 tick() 不会导致等待承诺完成(Karma/Jasmine)
【发布时间】:2019-04-29 10:11:31
【问题描述】:

我需要在 Angular 中创建一个测试规范,检查 base64 字符串是否转换为 Blob 对象。转换过程涉及嵌套承诺:

fetch(testImage1).then(res => res.blob()).then(blob => {});

我使用这个规范测试这个过程:

it( 'should update an image fakeAsync', fakeAsync( () => {
    fixture.detectChanges();
    let imgBlob = null;
    // testImage1 = 'data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z5......'
    fetch(testImage1).then(res => res.blob()).then(blob => {
        imgBlob = blob;
        expect(imgBlob).toBeTruthy(); //OK
    });
    tick();
    expect(imgBlob).toBeTruthy(); //test fails
} ));

如代码所示,spec 在 fakeAsync 块中运行,并且在异步代码调用之后调用 tick() 方法。 imgBlob 应该在 tick() 阻塞函数释放程序流之后设置。但是程序流程并没有停止,而是在异步调用完成之前检查第二个期望。这会导致规范失败。

Angular CLI 6.2.6、Karma 3.1.1、Jasmine 2.8.0

作为一种解决方法,这是可行的:

let promise = new Promise((resolve, reject) => {
        fetch(testImage1).then(res => res.blob()).then(blob => {
            resolve(blob);
        });

    });
    imgBlob = await promise;

【问题讨论】:

  • 您是在模拟/监视对fetch() 的调用,或者更具体地说是任何底层异步服务调用吗?如果是这样,请显示该代码。如果不是,那么这可能是您的问题 - 例如,如果有真正的异步代码尝试从真正的后端 API 获取数据,则 fakeAsync 将不起作用。
  • 据我了解,在这种情况下 fetch() 不应该向后端发出请求。它应该简单地将 base64 转换为 blob 对象。

标签: javascript angular karma-jasmine


【解决方案1】:

两件事:

首先,@dmcgrandle 是正确的,fakeAsync 依赖于猴子修补异步内置方法(或者更确切地说,它依赖于 Zone.js 修补它们),并且它明确不支持网络请求。至少,所有文档都说你不能使用 XHR,虽然我很惊讶地发现它没有明确说你也不能使用 fetch,但似乎就像一个非常安全的赌注。他们没有例外处理fetchdata: URL 的区别对待也不足为奇。即使它实际上并没有触发网络活动,它仍然使用 Promises 异步运行。

其次,我不确定您的真实代码是什么样的,但您编写的测试基本上是检查基本浏览器功能(或您的 polyfill?)是否正常工作。如果您实际上只需要从一些静态数据中创建 Blob,则可以使用更简单的方法来执行此操作,而无需调用 fetch

【讨论】:

    猜你喜欢
    • 2017-06-17
    • 2017-04-04
    • 2019-05-29
    • 2020-04-21
    • 2018-03-05
    • 1970-01-01
    • 2018-04-17
    • 2021-05-21
    • 2016-10-16
    相关资源
    最近更新 更多