【问题标题】:Test if a promise is resolved or rejected with Jasmine in Nodejs在 Nodejs 中使用 Jasmine 测试 promise 是否被解决或拒绝
【发布时间】:2015-01-25 16:21:08
【问题描述】:

我知道如何在 Mocha 中做到这一点,但想知道如何在 Jasmine 中做到这一点。 我试过这个

describe('test promise with jasmine', function() {
    it('expects a rejected promise', function() {
        var promise = getRejectedPromise();

        // return expect(promise).toBe('rejected');
        return expect(promise.inspect().state).toBe('rejected');
    });
});

但是,状态始终为pending,当然,测试失败。我在网上找不到任何可以让它工作的例子。

有人可以帮我解决这个问题吗?

谢谢。

【问题讨论】:

    标签: javascript node.js jasmine promise


    【解决方案1】:

    您现在可以使用expectAsync()

    期待成功:

    it('expect result', async () => {
       ...
       await expectAsync(someAsyncFunction(goodInput)).toBeResolved(expectedResponse)
    })
    

    预期失败:

    it('expect result', async () => {
       ...
       await expectAsync(someAsyncFunction(badInput)).toBeRejectedWith(expectedResponse)
    })
    

    【讨论】:

    • 附加说明:始终使用await (await expectAsync(...))是关键 - 否则测试将始终成功,无论是否承诺是否被拒绝,无论测试是否期望它被拒绝或解决!
    • 其实不然。它也可以从规范中返回。 return expectAsync(pi).toBeResolvedTo(3.14);
    • 这是最惯用的答案,应该被接受。 (当前接受的答案在给出时很好,但您的解决方案现在客观上更好。)
    【解决方案2】:

    要使用 jasmine 测试异步代码,您应该使用 its async syntax,例如:

    describe('test promise with jasmine', function(done) {
        var promise = getRejectedPromise();
    
        promise.then(function() {
          // Promise is resolved
          done(new Error('Promise should not be resolved'));
        }, function(reason) {
          // Promise is rejected
          // You could check rejection reason if you want to
          done(); // Success
        });
    });
    

    【讨论】:

    • 太棒了!如果你想检查被拒绝的错误内容怎么办?出于某种原因,我不断收到Error: Actual is not a functionExpected { _subscribers : [ ], _state : 0, _detail : { } } to throw error of type Function. 谢谢!
    • 太棒了!是的,这就是我正在做的事情......但如果我这样做 expect(reason).toEqual('someerrorstring'); 我会得到我提到的错误......
    • @Cmag 我建议首先手动检查拒绝原因,以确保它确实是您所期望的。只需使用console.log 或类似的东西。
    • @Cmag 我建议检查它是否是 Error 类的实例,并且它包含带有预期错误消息的 msg 属性。
    • 从 jasmine ^2.3 开始,我无法将参数传递给 done 函数。最好使用done.fail(new Error('error message'))Reference to documentation
    【解决方案3】:

    jasmine 2.7 及以后版本支持返回承诺,并将对其完成状态进行测试。

    测试拒绝:

    it('test promise with jasmine', async () => {
        try {
            await getRejectedPromise();
        } catch (err) {
            return;
        }
    
        throw new Error('Promise should not be resolved');
    });
    

    还是:

    it('test promise with jasmine', async () => {
        await getRejectedPromise()
            .then(
                () => Promise.reject(new Error('Promise should not be resolved')), 
                () => {});
    });
    

    要验证实际消息,除了通常的instanceof/toBe(),请放在catch 内:

    expect(() => { throw err }).toThrow(new MyCustomError('Custom error message'));
    

    这种方法的好处是在测试输出上有更好的失败消息。

    预期函数会抛出 MyCustomError:自定义错误消息,但它抛出了另一个错误消息。

    比通常的输出要好一些。

    测试已解决(再简单不过了):

    it('test promise with jasmine', async () => {
        await getRejectedPromise();
    });
    

    【讨论】:

    • try/catch 是几乎所有编程语言中最丑陋的编码结构,imo
    • @AlexanderMills 我知道你在开玩笑,但我很久以前就从简单的 promises/then 切换到 async/await。 Ofc 我在有意义的时候使用“旧方式”。
    • 如果你在getRejectedPromise()上面添加一个promise,这段代码会吞下错误,因为在错误处理程序中没有检查发生什么类型的错误。
    • 因此这段代码并不是真正用于一般用途,它是“漂亮”的简写。
    【解决方案4】:

    您可以使用finally 块来测试承诺状态:

    it('should resolve if auth succeed', (done)=>{
        var p = server.login('user', 'password');
        p.finally(()=>{
            expect(p.isFulfilled()).toBeTruthy();
            done();
        });
    });
    

    您可以使用isFulfilled 检查承诺是否已履行,并使用value 方法检查履行值。对应的拒绝方法为isRejectedreason

    【讨论】:

    • 使用这个方法,如何检查promise是否被拒绝,以及查看reject消息?
    • @RuiMarques 你可以使用isRejectedreason 方法。我更新了我的答案。
    • finally()isFulfilled() 不是标准的(截至 2017 年)。请编辑您的答案以指定外部要求。
    • 这个答案在几个方面是错误的:(1)isFulfilled() 不是根据 ECMAScript 标准的Promise 的官方方法。 (2) 即使是这样,它总是会在finally 中返回true,因为fulfilled 表示承诺要么被rejected 要么resolved,这总是当finally 被调用时为真。
    【解决方案5】:

    @Leonid 的回答是正确的,但你可以像这样简化,并且只使用 Promise:

    it('test promise with jasmine', function() {
    
        return getRejectedPromise().then(function() {
          // Promise should not be resolved, so we reject it
          return Promise.reject(new Error('Promise should not be resolved'));
        })
        .catch(function(err){
           if(!/Promise should not be resolved/.test(err && err.message)){
              return Promise.reject(err);
           }
        })
    })
    

    【讨论】:

    • 同意。由于丑陋的 catch 条款,我撤回了我的支持。其他人投了反对票,可能是因为缺少此注释并认为它不起作用。
    • catch 子句是它正常工作所必需的,它是 Promises 的普通 API,我不认为它难看......你会为了让它更漂亮而错误地编码吗?哈哈
    • test() 是针对上面几行抛出的错误,它是丑陋和懒惰的编码。看我的回答。
    • @AndréWerlang 嗯,有时您需要测试错误消息,有时需要使用 catch 块,在这种情况下可能不是,但我认为我的更通用,如果您需要添加更多承诺这条链子在路上。
    猜你喜欢
    • 2023-04-03
    • 2020-04-15
    • 2019-04-17
    • 2019-10-25
    • 1970-01-01
    • 2018-02-25
    • 2017-03-14
    • 1970-01-01
    • 2015-08-31
    相关资源
    最近更新 更多