似乎承诺 不要在 Angular/Jasmine 测试中解析,除非你强制 $scope.$digest(). 。在我看来,这是愚蠢的,但没关系,我在适用的情况下可以使用它(控制器)。

我现在所处的情况是我有一个服务,它不太关心应用程序中的任何范围,它所做的只是从服务器返回一些数据,但承诺似乎没有得到解决。

app.service('myService', function($q) {
  return {
    getSomething: function() {
      var deferred = $q.defer();
      deferred.resolve('test');
      return deferred.promise;
    }
  }
});

describe('Method: getSomething', function() {
  // In this case the expect()s are never executed
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
    });

    done();
  });

  // This throws an error because done() is never called.
  // Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
      done();
    });
  });
});

测试此功能的正确方法是什么?

编辑:解决方案供参考。显然,即使服务没有使用它,您也被迫注入并消化 $rootScope 。

  it('should get something', function($rootScope, done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
    });

    $rootScope.$digest();
    done();
  }); 
有帮助吗?

解决方案

您需要在测试中注入生成的生成鸟类代码,并触发生成的$rootScope

其他提示

总是有$ rootscope,使用它

inject(function($rootScope){
myRootScope=$rootScope;
})
....

myRootScope.$digest();
.

所以整个下午我都在为此苦苦挣扎。读完这篇文章后,我也觉得答案有问题;事实证明是有的。上述答案都没有明确解释在何处以及为何使用 $rootScope.$digest. 。所以,这就是我的想法。

首先为什么?你需要使用 $rootScope.$digest 每当您响应非角度事件或回调时。这将包括纯 DOM 事件、jQuery 事件和除 $q 这是角度的一部分。

其次在哪里?在您的代码中,而不是您的测试中。无需注射 $rootScope 在您的测试中,只有在实际的角度服务中才需要它。他们表明,这就是上述所有内容都未能明确答案的地方 $rootScope.$digest 从测试中调用。

我希望这可以帮助下一个长期遇到同样问题的人。

更新


昨天这篇文章被否决后我就把它删除了。今天,我在尝试使用上面慷慨提供的答案时仍然遇到这个问题。因此,我以声誉点为代价来保留我的答案,因此,我将取消删除它。

这就是您在非角度事件处理程序中所需要的,并且您正在使用 $q 并尝试使用 Jasmine 进行测试。

something.on('ready', function(err) {
    $rootScope.$apply(function(){deferred.resolve()});              
});

请注意,在某些情况下,它可能需要包含在 $timeout 中。

something.on('ready', function(err) {
    $timeout(function(){
      $rootScope.$apply(function(){deferred.resolve()});    
    });     
});

还有一点注意。在您调用的原始问题示例中 done 在错误的时间。你需要打电话 done 里面的 then 方法(或 catch 或者 finally)的承诺,之后就是解决。您在承诺解决之前调用它,这导致 it 终止条款。

从角度文档。

https://docs.angularjs.org/api/ng/service/ $ q

it('should simulate promise', inject(function($q, $rootScope) {
  var deferred = $q.defer();
  var promise = deferred.promise;
  var resolvedValue;

  promise.then(function(value) { resolvedValue = value; });
  expect(resolvedValue).toBeUndefined();

  // Simulate resolving of promise
  deferred.resolve(123);
  // Note that the 'then' function does not get called synchronously.
  // This is because we want the promise API to always be async, whether or not
  // it got called synchronously or asynchronously.
  expect(resolvedValue).toBeUndefined();

  // Propagate promise resolution to 'then' functions using $apply().
  $rootScope.$apply();
  expect(resolvedValue).toEqual(123);
}));
.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top