【问题标题】:Angular $q.when is not resolved in Karma unit testAngular $q.when 在 Karma 单元测试中未解决
【发布时间】:2014-06-13 18:00:31
【问题描述】:

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

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;
    }
  }
})

【问题讨论】:

  • 为什么要同时使用 Q 和 $q?也许 Karma(或它使用的 AngularMocks 库)期待由 $q.defer() 而不是 Q.defer() 生成的承诺
  • 我使用 PouchDB,它有自己的 promise,所以我需要用 $q 包装它们。我在示例中使用 Q 只是为了简化事情 - 结果是一样的:$q.when 在包装外部承诺时没有在 Karma 中解决,这是 BTW 的主要目的 $q.when

标签: angularjs jasmine karma-runner


【解决方案1】:

How to resolve $q.all promises in Jasmine unit tests?看来,诀窍是:

$rootScope.$apply();

我也遇到了同样的问题,这对我有用;进行此调用时,承诺已得到解决。

【讨论】:

    【解决方案2】:

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

    唯一缺少的其他细节是您在此测试套件中没有 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
    
        });
    });
    

    【讨论】:

    • 我的准备工作很简单,我没有创建新的范围(我编辑了问题)我尝试使用 $timeout 并刷新...没有任何改变
    • 尝试创建新范围并删除超时。
    • 我不明白为什么它会改变任何东西 - 我没有明确使用 $scope,反正它不起作用。
    • 伙计,done() 是用于 Karma 内部异步测试的 Jasmine 函数。如果无法访问代码,则断言并不重要。
    • 我从来没有理由使用 done() 并且倾向于忘记它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    相关资源
    最近更新 更多