首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >承诺在安古拉杰茉莉花试验中太迟了

承诺在安古拉杰茉莉花试验中太迟了
EN

Stack Overflow用户
提问于 2015-12-11 16:21:42
回答 1查看 1.4K关注 0票数 3

我有以下用ng-describe编写的茉莉测试,用karma运行。

(我正在使用ES6-承诺填充PhantomJS)

代码语言:javascript
复制
var myModule = angular.module('MyModule', []);
myModule.service('MyService', [function() {
  return {
    getItems: function() {
      // this will be spied and mocked
    }
  };
}]);

myModule.controller('MyController', ['$scope', 'MyService',
  function($scope, MyService) {
    $scope.items = [];

    $scope.refreshItems = function() {
      MyService.getItems().then(
        function ok(items) {
          $scope.items = items;
          console.log('OK, items.length = ' + items.length);
        },
        function fail(reason) {
          console.error('FAIL')
        }).catch(console.error.bind(console));
    };
  }
]);

ngDescribe({
  name: "MyController test",
  modules: ['MyModule'],
  inject: ['MyService', '$rootScope', '$q'],
  controllers: 'MyController',
  tests: function(deps) {

    function getPromise(val) {
      return new Promise(function(resolve, reject) {
        resolve(val);
      });
    }

    it('updates $scope.items', function() {
      spyOn(deps.MyService, 'getItems').and.returnValue(getPromise([4, 5, 6]));
      deps.MyController.refreshItems();
      deps.$rootScope.$digest();

      expect(deps.MyService.getItems).toHaveBeenCalled();
      expect(deps.MyController.items.length).toBe(3);
      console.log("END OF TEST");
    });
  }
});

测试将失败,因为承诺被解决得太晚了:

代码语言:javascript
复制
LOG: 'END OF TEST'
PhantomJS 1.9.8 (Windows 7 0.0.0) MyController test updates $scope.items FAILED
        Expected 0 to be 3.
            at d:/git/myproject/test/controllers/ItmngtControllerTest.js:49
LOG: 'OK, items.length = 3'
PhantomJS 1.9.8 (Windows 7 0.0.0): Executed 37 of 37 (1 FAILED) (0.085 secs / 0.26 secs)

经过太长时间的调查,我发现如果我使用$q而不是Promise,它就会工作得很好。

代码语言:javascript
复制
    function getPromise(val) {
      var deferred = deps.$q.defer();
      deferred.resolve(val);
      return deferred.promise;
    }

但是,我想知道为什么会出现这种情况,我可以在测试中更改一些东西,使用Promise而不是$q来通过测试吗?

我在很多地方都读过关于$rootScope.$apply()的文章,但是不管我把它放在哪里,它对我来说还是行不通的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-11 17:46:30

角度$q测试是同步的,这是一个巨大的优势。一旦范围$digest()被调用,就可以预期所有$q承诺链处理程序也会被调用。

另一方面,承诺(包括ES6实现)在设计上是异步的。一旦承诺被解决,它的处理程序将在下一个滴答中被调用。所以愉快的角度测试不再是同步的了:

代码语言:javascript
复制
it('updates $scope.items', function (done) {
  ...
  setTimeout(() => {
    expect(deps.MyService.getItems).toHaveBeenCalled();
    expect(deps.MyController.items.length).toBe(3);
    console.log("END OF TEST");
    done();
  });
});

为了测试的目的,可以对Promise进行模拟,以实现同步,在这种情况下可以使用mock-promises

还有jasmine-co,它的目的是使ES6生成器和co在茉莉花中的异步测试更容易(实际上也是如此),我不知道它在ng-describe中的性能有多好。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34228045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档