在Karma单元测试中未解决Angular $ q.when

时间:2014-06-13 18:00:32

标签: angularjs jasmine karma-runner

我使用 $ q.when 来包装其他lib承诺。 它就像一个魅力,但是当我尝试在Karma中运行它时,即使我运行 $ digest ,甚至在运行 $ digest 后,承诺仍然无法解决(完成()永远不会执行)超时。 以下是示例代码:

describe('PouchDB', function () {
var $q, $rootScope;

beforeEach(inject(function (_$rootScope_, _$q_) {
    $rootScope = _$rootScope_;
    $q = _$q_;
}));

it("should run", function (done) {

    function getPromise() {
        var deferred = Q.defer();

        deferred.resolve(1);

        return deferred.promise;
    }

    $q.when(getPromise())
        .then(function () {
            done();   // this never runs
        });

    $rootScope.$digest();
});

为什么呢?这是什么原因?我真的无法得到它。

更新(解决方法)

我不明白为什么$ q.when在Karma中没有得到解决 - 它有一些nextTick函数,但我无法调试问题。 相反,我放弃了$ q.when并编写了简单的函数,将PouchDB(或任何其他像Q)转换为$ q:

.factory('$utils', function ($q, $rootScope) {
  return {
    to$q: function (promise) {
      var deferred = $q.defer();

      promise.then(function (result) {
        deferred.resolve(result);
        $rootScope.$digest();
      });

      promise.catch(function (error) {
        deferred.reject(error);
        $rootScope.$digest();
      });

      return deferred.promise;
    }
  }
})

2 个答案:

答案 0 :(得分:21)

来自How to resolve $q.all promises in Jasmine unit tests?似乎诀窍是:

$rootScope.$apply();

我遇到了同样的问题,这对我有用;做出这个电话时,承诺得到了解决。

答案 1 :(得分:1)

我已经调整了变量并注入了依赖项名称,以便在测试编写继续时保持清晰。如果done()是你的(控制器?指令?service / factory?)中的一个函数,那么应该在测试运行时调用它而不试图将它作为依赖项传递。理想情况下应该监视done(),但不知道它来自哪里,就不可能向你展示如何设置间谍功能。

缺少的唯一其他细节是您在此测试套件中没有expect()。没有它,我无法知道你期望被断言的东西。

describe('PouchDB', function () {
    var scope, db, q, rootScope;

    beforeEach(
        inject(
            function(_$rootScope_, _$q_){
                rootScope = _$rootScope_;
                scope = rootScope.$new();
                q = _$q_;
            }
        )
    );

    it("should run", function(){

        //spy should be constructed here

        function getPromise() {
            var deferred = q.defer();

            deferred.resolve(1);

            return deferred.promise;
        }

        q.when(getPromise)
            .then(function () {
                done();
            });

        scope.$digest();

        //assertion should be here

    });
});