在 Nodejs 中使用 Jasmine 测试 promise 是不是被解决或拒绝

Posted

技术标签:

【中文标题】在 Nodejs 中使用 Jasmine 测试 promise 是不是被解决或拒绝【英文标题】: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,当然,测试失败。我在网上找不到任何可以让它工作的例子。

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

谢谢。

【问题讨论】:

【参考方案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 块,在这种情况下可能不是,但我认为我的更通用,如果您需要添加更多承诺这条链子在路上。

以上是关于在 Nodejs 中使用 Jasmine 测试 promise 是不是被解决或拒绝的主要内容,如果未能解决你的问题,请参考以下文章

单元测试 jasmine

如何使用node.js jasmine设置断点?

使用Jasmine和karma对传统js进行单元测试

JavaScript单元测试框架-Jasmine

使用 Jasmine 测试 Node 项目

在Visual Studio 2013中使用Jasmine + Karma进行AngularJS测试