Angularjs摩卡测试$q承诺,无$rootScope。$apply

Angularjs摩卡测试$q承诺,无$rootScope。$apply,angularjs,mocha.js,angular-promise,chai,karma-mocha,Angularjs,Mocha.js,Angular Promise,Chai,Karma Mocha,我有以下服务: angular.module('domeeApp') .factory('streamWidget', streamWidgetFactory); function streamWidgetFactory($q) { return { loadContent: function() { return $q(function(resolve, reject) {

我有以下服务:

    angular.module('domeeApp')
        .factory('streamWidget', streamWidgetFactory);

    function streamWidgetFactory($q) {
        return {
            loadContent: function() { 
                return $q(function(resolve, reject) {
                    resolve('test');
                }) 
            }
        }
    }
我正在用karma/mocha/chai测试它:

describe('streamWidget', function() {
    beforeEach(module('domeeApp'));
    var streamWidget;
    var $timeout;

    beforeEach(inject(function(_$timeout_, _streamWidget_) {
        streamWidget = _streamWidget_;
        $timeout = _$timeout_;
    }));


    it('should load new content', function(done) {        
        streamWidget.loadContent()
        .then(function(res) {
            expect(res).to.equal('test');
            done();
        })
        .catch(function(){})
        $timeout.flush();
    });    
});
由于$q promises不能很好地与mocha配合使用,我将遵循下面的说明,即添加
$timeout.flush()
以强制执行promise的
。然后执行
方法

问题是,在调用.flush()之后,我的所有应用程序都会被唤醒,我开始从角度模拟中获得以下错误:

错误:意外请求:GET/partials/page/view/index

我知道大约$httpBackend,但模仿我的应用程序在启动时发出的所有请求将是疯狂的

有没有一种方法可以使
$q
承诺在不调用
$timeout.flush()
$rootScope.$apply()
的情况下与摩卡一起工作?
如图所示,可以使用
承诺的chai
来断言
$q
承诺。 使用此设置

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

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

  inject(function ($rootScope) {
    if (!$rootScope.$$phase)
      $rootScope.$digest();
  });
};
摘要周期将在承诺断言时自动触发,执行整个承诺链

在这种情况下,规范

it('...', () => {
  ...
  expect(...).to.eventually...;
  expect(...).to.eventually...;
  $rootScope.$digest();
});
可以省略
$digest()
调用并成为

it('...', () => {
  ...
  expect(...).to.eventually...;
  expect(...).to.eventually...;
});

请注意,
$q
承诺是同步的,它们不应该从Mocha spec返回,也不应该调用
done
回调。

我们使用另一种策略,因为我们实际上不需要
$httpBackend
,但它有时(随机)无法请求指令使用的模板(即使这些模板在
$templateCache
中可用):


当然,如果您在其他情况下实际使用了
$httpBackend
,那么这将不起作用,因为您需要它来模拟响应对象。

问题的主题是Chai,而不是Mocha。问题主题的可能重复是$q服务,以及我如何在不使用apply/flush.Chai的情况下强制解决$q承诺G是为了解决这个问题,因为我并没有像我所承诺的那样使用CHAI。至少,这是我看到的情况,如果你不同意的话,试着更好地解释它。这是CHAI做的断言,而不是摩卡。那么,你可以考虑使用CHAI作为承诺,那就是如何在不调用<代码> $Apple()/<代码>或<代码> $Digeste()的情况下完成Q承诺断言的方式。
之后
。我按照承诺尝试了chai,但结果相同。如果您能向我展示一个有效的解决方案,我将接受您的回答。是的,
按照承诺的chai
需要一些额外的设置,正如上面的链接所示。幸运的是,它有了
transferPromiseness
钩子来为客户提供所需的行为sserted promise(即运行摘要以执行整个承诺链)。我尝试了您的解决方案,但结果相同。当我调用
$rootScope.$digest()时
,无论是在
ChaiasPromission.transferPromiseness
还是在其他地方,我都会遇到与意外请求相同的错误。事实上,我从一开始就想知道如何在不使用$digest/$apply/$flush的情况下进行此测试。目前我想没有解决方案。似乎您将这些问题混淆了。这些都是单独的问题cerns。
$digest()
不是万灵药。您需要触发
$digest()
来执行$q承诺(这就是答案)。您需要调用
flush()
执行$timeout超时。您需要在单元测试中模拟$httpBackend请求。不需要模拟所有请求-只模拟被测试单元发出的请求。角度测试就是这样工作的。
beforeEach(function() {
  module('app', function($provide) {
    // This is using jasmine, but the idea is the same with mocha.
    // Basically just replace $httpBackend with a function that does nothing.
    $provide.constant('$httpBackend', jasmine.createSpy('$httpBackend'));
  });
});