我正在尝试使chai-as-promised与 karma 单元测试中的$q promises一起使用。

  svc.test = function(foo){
    if (!foo){
      // return Promise.reject(new Error('foo is required'));
      return $q.reject(new Error('foo is required'));
    } else {
      // get data via ajax here
      return $q.resolve({});
    }
  };


  it.only('should error on no foo', function(){
    var resolvedValue = MyServices.test();
    $rootScope.$apply();
    return resolvedValue.should.eventually.be.rejectedWith(TypeError, 'foo is required');
  });

单元测试只是超时。我不确定我在这里做错了什么,以答应妥善解决。使用$q似乎是一个问题-当我使用 native Promise.reject()时,它可以正常工作。

我在这里提交了一张票,但似乎没有人回应:
https://github.com/domenic/chai-as-promised/issues/150

最佳答案

chai-as-promised期望修改 promise 断言的方式是 transferPromiseness method



为了支持Angular 1.3+,可以通过$q属性将$$state promise 转为鸭子类型,因此 native promise 不会受到影响:

chaiAsPromised.transferPromiseness = function (assertion, promise) {
  assertion.then = promise.then.bind(promise);

  if (!('$$state' in promise))
    return;

  inject(function ($rootScope) {
    if (!$rootScope.$$phase)
      $rootScope.$digest();
  });
};
chaiAsPromisedthen链接每个断言的Promise。即使实现了 promise ,链的其余部分仍然需要使用$rootScope.$digest()手动触发摘要。

只要规范不包含异步代码,它就会变为同步代码,不需要返回任何保证:
it('...', () => {
  ...
  expect(...).to.eventually...;
  expect(...).to.eventually...;
});

并且在未设置$rootScope.$digest()的情况下,在每组eventually断言/期望之后等于强制性transferPromiseness:
it('...', () => {
  ...
  expect(...).to.eventually...;
  expect(...).to.eventually...;
  $rootScope.$digest();
});

10-07 12:39