Jasmine:如何期望承诺处理程序不抛出异常

Jasmine: How to expect promise handler to not throw exception

我有这个功能:

reload() {
    myService.queryData()
        .done(...)
        .always(() => throw "fake exception"); //just to simulate the failure
}

我想要我的测试重载函数并确保它不会抛出异常,promise 回调也不会抛出异常。

describe("reload", function () {
    it("does not throw exception", function (done) {

        spyOn(myService, "queryData").and.callFake(() => {
            let deffered = $.deffered();
            setTimeOut(() => deffered.reject(), 0)
            return deffered.promise();
        });

        reload();
        setTimeout(() => {
           //this is evaluated after the exception has been thrown, but
           //how to check whether exception has been thrown
        }, 2);
    });
});

编辑:在某些情况下,我可能无法 return 承诺,其中函数的 return 类型已经定义,例如组件的生命周期事件:

MyComponent extends React.Component {
    componentDidMount() {
        this.load(
            galleryService.nodes().then(galleryResult => this.setState({ nodes: galleryResult.nodes }))
        );
        this.load(
            galleryService.caches().then(cachesResult => this.setState({ caches: cachesResult.caches }))
        );
    }
}

var myComponent = React.createElement(MyComponent);
TestUtils.renderIntoDocument(myComponent); //this triggers the componentDidMount event and I need to make sure it won't throw error.

reloadreturn它创造的承诺。在您的测试用例中,将 catch 处理程序附加到它会触发测试失败:

reload().catch(err => done.fail(err));

编辑问题后更新: 如果您无法更改原始函数的 return 值,则将相关部分分解为单独的函数。例如:

function reloadNodes() {
    return somePromise();
}

function reloadCaches() {
    return anotherPromise();
}

function reload() {
    reloadNodes();
    reloadCaches();
}

然后您可以测试 reloadNodesreloadCaches 而不是 reload。显然,您不需要为每个承诺创建单独的函数,而是在适当的地方使用 Promise.all 之类的东西组合您的承诺。

我认为监视 window.onerror 是正确的做法:

describe("reload", function () {
    it("does not throw an exception", function (done) {

            spyOn(window, 'onerror').and.callFake((error: any, e: any) => {
                fail(error);
            });

            spyOn(myService, "queryData").and.callFake(() => {
               let deffered = $.deffered();
               setTimeout(deffered.reject, 0);
               return deffered.promise();
           });
        });
        setTimeout(done, 2);
    });
});