首页 > 解决方案 > 在嵌套承诺之后使用 tick() 不会导致等待承诺完成(Karma/Jasmine)

问题描述

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

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() 阻塞函数释放程序流之后设置。但是程序流程并没有停止,而是在异步调用完成之前检查第二个期望。它导致规范失败。

角 CLI 6.2.6、业力 3.1.1、茉莉花 2.8.0

作为一种解决方法,这有效:

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

    });
    imgBlob = await promise;

标签: javascriptangularkarma-jasmine

解决方案


两件事情:

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

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


推荐阅读