Angularjs 角度及;Jasmine:如何测试$q承诺链是否已解决

Angularjs 角度及;Jasmine:如何测试$q承诺链是否已解决,angularjs,jasmine,promise,angular-promise,Angularjs,Jasmine,Promise,Angular Promise,我有一个服务,它公开一个函数,该函数接收解析的CSV(使用),并承诺反映解析状态: 如果文件缺少必填字段,则承诺将被拒绝 否则,它会将每一行解析为一个项目,并自动填充缺少的字段(自动填充过程是异步的)。 填充所有项后,函数将使用项数组解析承诺 我要测试的函数是onCsvParse: angular.module('csvParser', []) .factory('csvParser', ['$http', function($http) { var service =

我有一个服务,它公开一个函数,该函数接收解析的CSV(使用),并承诺反映解析状态:
如果文件缺少必填字段,则承诺将被拒绝
否则,它会将每一行解析为一个项目,并自动填充缺少的字段(自动填充过程是异步的)。
填充所有项后,函数将使用项数组解析承诺

我要测试的函数是onCsvParse:

angular.module('csvParser', [])
  .factory('csvParser', ['$http',
    function($http) {
      var service = {
        onCsvParse: function(results, creatingBulkItems) {
          var errors = this.getCsvErrors(results);
          if (errors.length > 0) {
            //reject
            creatingBulkItems.reject(errors);
          } else {

            var items = this.parseCsv(results);
            var autoPopulateItems = [],
              populatedItems = [];
            for (var i = 0; i < populatedItems.length; i++) {
              var item = items[i];
              if (item.name === "" /*or some any field is missing */ ) {
                // auto populate item
                autoPopulateItems.push(this.autoPopulateItem(item));
              } else {
                var populatedItem = $q.when(item);
                populatedItems.push(populatedItem);
              }
            }
            populatedItems =autoPopulateItems.concat(populatedItems);
            var populatingAllItems = $q.all(populatedItems);
            populatingAllItems.then(function(items) {
              creatingBulkItems.resolve(items);
            }, function(err) {
              creatingBulkItems.resolve(err);
            });
          }
        },
        autoPopulateItem: function(newItem) {
          var populatingItem = $q.defer();
          var item = angular.copy(newItem);
          $http.post('api/getItemData', { /*.....*/ })
            .success(function(response) {
              //----Populate item fields
              item.name = response.name;
              //....
              //resolve the promise
              populatingItem.resolve(item)

            }).error(err) {
              // resolving on error for $q.all indication
              populatingItem.resolve(item)
            };
          return populatingItem.promise;

        }
      }
      return service;
    }
  ])
这样我得到了一个错误:error:Timeout-Async回调没有在jasmine.DEFAULT\u Timeout\u INTERVAL指定的超时内调用

虽然我调用了$rootScope.$apply(),而且我也没有调用真正的异步调用(只调用mock,除了$q.all),但承诺没有得到解决。
如何使其工作?

无效语法。您需要将函数传递给
错误
回调

        }).error(function(err) {
          // resolving on error for $q.all indication
          populatingItem.resolve(item)
        });
      return populatingItem.promise;
此外,jasime测试还需要一些初始化:
读完这篇文章后:我发现了我的问题。
关键点是使用承诺展平承诺链,然后返回值

此[promise.then]函数应返回一个新的承诺,该承诺在给定的fulfilledHandler或errorHandler回调完成时实现。这允许promise操作链接在一起。回调处理程序返回的值是返回的承诺的实现值。如果回调抛出错误,则返回的承诺将移至失败状态

不是在内部承诺成功/失败回调中解析外部承诺,而是在内部承诺中解析外部承诺。然后在回调中解析外部承诺

所以我的解决方案是这样的:

onCsvParse: function(results) {
      var errors = this.getCsvErrors(results);
      if (errors.length > 0) {
         var deferred = $q.defer();
        //reject
        return deferred.reject(errors);
      } else {

        var items = this.parseCsv(results);
        var autoPopulateItems = [],
          populatedItems = [];
        for (var i = 0; i < populatedItems.length; i++) {
          var item = items[i];
          if (item.name === "" /*or some any field is missing */ ) {
            // auto populate item
            autoPopulateItems.push(this.autoPopulateItem(item));
          } else {
            var populatedItem = $q.when(item);
            populatedItems.push(populatedItem);
          }
        }
        populatedItems = autoPopulateItems.concat(populatedItems);
        var populatingAllItems = $q.all(populatedItems);
        return populatingAllItems.then(function(items) {
            return items;
        }, function(err) {
          return err;
        });
      }
    },

注意:此代码工作正常,我可以浏览csv,将其解析为项目并自动填充,问题在于测试该功能。我试图在这里只留下相关的代码,因此可能会有小的复制粘贴错误。我看不出您自己的角度服务与尝试测试和在线解析之间有任何关联service@yarons根据给出的代码,答案是“不”,我不小心删除了上面的评论。您是否将工厂注入到测试脚本中?我没有复制所有代码,因为我认为这与此无关:Papa-我在问题中提到的papaparse库getCsvErrors-也与此无关,因为我专注于解析过程。完整代码将csv解析为项目properly@AdiV发布您知道不正确的代码不是提问的好方法。@Michael此Plunker不可用。
onCsvParse: function(results) {
      var errors = this.getCsvErrors(results);
      if (errors.length > 0) {
         var deferred = $q.defer();
        //reject
        return deferred.reject(errors);
      } else {

        var items = this.parseCsv(results);
        var autoPopulateItems = [],
          populatedItems = [];
        for (var i = 0; i < populatedItems.length; i++) {
          var item = items[i];
          if (item.name === "" /*or some any field is missing */ ) {
            // auto populate item
            autoPopulateItems.push(this.autoPopulateItem(item));
          } else {
            var populatedItem = $q.when(item);
            populatedItems.push(populatedItem);
          }
        }
        populatedItems = autoPopulateItems.concat(populatedItems);
        var populatingAllItems = $q.all(populatedItems);
        return populatingAllItems.then(function(items) {
            return items;
        }, function(err) {
          return err;
        });
      }
    },
it('Should not fail :)', function(done) {
csvParser.onCsvParse(csvResults).then(function(items) {
  //promise is resolved
  expect(items).not.toBeNull();
  done();
}, function() {
  //promise is rejeceted
  //expect(1).toEqual(1);
  done();
});
$rootScope.$apply();});