javascript - Angularjs promise 在单元测试中未得到解决

标签 javascript unit-testing angularjs jasmine

我正在使用 jasmine 对 angularjs Controller 进行单元测试,该 Controller 将范围上的变量设置为调用返回 Promise 对象的服务方法的结果:

var MyController = function($scope, service) {
    $scope.myVar = service.getStuff();
}

服务内部:

function getStuff() {
    return $http.get( 'api/stuff' ).then( function ( httpResult ) {
        return httpResult.data;
    } );
}

这在我的 angularjs 应用程序的上下文中工作正常,但在 jasmine 单元测试中不起作用。我已经确认“then”回调正在单元测试中执行,但 $scope.myVar promise 永远不会设置为回调的返回值。

我的单元测试:

describe( 'My Controller', function () {
  var scope;
  var serviceMock;
  var controller;
  var httpBackend;

  beforeEach( inject( function ( $rootScope, $controller, $httpBackend, $http ) {
    scope = $rootScope.$new();
    httpBackend = $httpBackend;
    serviceMock = {
      stuffArray: [{
        FirstName: "Robby"
      }],

      getStuff: function () {
        return $http.get( 'api/stuff' ).then( function ( httpResult ) {
          return httpResult.data;
        } );
      }
    };
    $httpBackend.whenGET( 'api/stuff' ).respond( serviceMock.stuffArray );
    controller = $controller( MyController, {
      $scope: scope,
      service: serviceMock
    } );
  } ) );

  it( 'should set myVar to the resolved promise value',
    function () {
      httpBackend.flush();
      scope.$root.$digest();
      expect( scope.myVar[0].FirstName ).toEqual( "Robby" );
    } );
} );

此外,如果我将 Controller 更改为以下内容,单元测试就会通过:

var MyController = function($scope, service) {
    service.getStuff().then(function(result) {
        $scope.myVar = result;
    });
}

为什么 promise 回调结果值没有传播到单元测试中的 $scope.myVar ?请参阅以下 jsfiddle 了解完整的工作代码 http://jsfiddle.net/s7PGg/5/

最佳答案

我猜这个“谜团”的关键在于,如果模板中的插值指令中使用了 promise (并渲染结果),AngularJS 将自动解析 promise (并呈现结果)。我的意思是给定这个 Controller :

MyCtrl = function($scope, $http) {
  $scope.promise = $http.get('myurl', {..});
}

和模板:

<span>{{promise}}</span>

AngularJS 在 $http 调用完成后,将“看到” promise 已解决,并将使用已解决的结果重新渲染模板。这就是$q documentation中隐约提到的内容。 :

$q promises are recognized by the templating engine in angular, which means that in templates you can treat promises attached to a scope as if they were the resulting values.

可以看到发生这种魔法的代码 here .

但是,只有当有模板(更准确地说,$parse 服务)在起作用时,这种“魔力”才会发生。 在您的单元测试中,不涉及模板,因此 promise 解析不会自动传播

现在,我必须说这种自动解析/结果传播非常方便,但可能会令人困惑,正如我们从这个问题中看到的那样。这就是为什么我更喜欢像您一样显式传播解析结果:

var MyController = function($scope, service) {
    service.getStuff().then(function(result) {
        $scope.myVar = result;
    });
}

关于javascript - Angularjs promise 在单元测试中未得到解决,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15048132/

相关文章:

javascript - Eloquent Javascript 中的练习 4.4 -- startsWith() 和 .slice

javascript - 删除 <span> 标签,同时保留内容完好无损,仅使用 javascript

javascript - 滚动时如何粘贴静态标题

java - 单元测试嵌套子流(子流的子流)

javascript - 使用字符串作为名称创建对象

javascript - 动画进度条?

javascript - Jasmine 测试 postMessage API

unit-testing - 运行所有 zend framework2 单元测试

javascript - 在 Angular Controller 中使用 moment-duration-format 插件

javascript - 如何避免使用 Ecma 6 编写的新 Angular 组件?