当前位置: 首页 > 面试题库 >

AngularJS承诺不会在单元测试中解决

寿元白
2023-03-14
问题内容

我正在使用茉莉花对angularjs控制器进行单元测试,该控制器在范围内将变量设置为调用返回promise对象的服务方法的结果:

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

服务内部:

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

在我的angularjs应用程序上下文中,这可以正常工作,但在茉莉花单元测试中则无法工作。我已经确认“ then”回调在单元测试中正在执行,但是$
scope.myVar承诺永远不会设置为回调的返回值。

我的单元测试:

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

另外,如果我将控制器更改为以下单元测试通过:

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

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


问题答案:

我想这个“谜”的关键在于,如果在模板的插值指令中使用了承诺,AngularJS将自动解决承诺(并渲染结果)。我的意思是给定此控制器:

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

和模板:

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

在$ http调用完成后,AngularJS将“看到”一个承诺已解决,并将使用已解决的结果重新呈现模板。这就是$
q文档中
模糊提及的内容:

$ qpromise由模板引擎以角度识别,这意味着在模板中,您可以将附加到作用域的promise视为它们的结果值。

可以在此处看到发生这种魔术的代码

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

现在,我必须说这种自动解析/结果传播非常方便,但可能会造成混淆,正如我们从这个问题可以看到的那样。这就是为什么我更喜欢像您那样显式传播分辨率结果的原因:

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


 类似资料:
  • 问题内容: 在Angular中,所有内容似乎都具有陡峭的学习曲线,并且对Angular应用程序进行单元测试绝对不能逃脱这种范例。 当我开始使用TDD和Angular时,我觉得我花了两倍(可能更多)的时间来弄清楚如何测试,甚至花更多的时间来正确地设置测试。但是正如Ben Nadel 在他的博客中所说的那样,角度学习过程存在起伏。他的图表绝对是我在Angular的经历。 但是,随着我在学习Angula

  • 问题内容: 根据Michal Charemza帖子编辑。 我有一个代表angularui模态对话框的服务: 如果用户单击对话框中的“确定”,则在调用delete方法时将执行。 问题是我无法对此进行单元测试。 这是我的考验。我已经正确注入了q服务,但是我不确定应该从间谍那里返回什么… 但是我正在接受。这意味着…部分没有执行。我想念什么? 问题答案: 要模拟返回承诺的函数,它还需要返回承诺,然后需要将

  • 问题内容: 我的控制器具有如下代码: 在我的单元测试中,我正在做这样的事情: 现在在测试中,我正在检查是否调用了服务,并且data1,data2是否未定义。 我的问题是,这是工作的罚款,直到我取代与q.all控制器和测试我个人的服务电话与。使用q.all和(也尝试使用),两个测试均失败,并显示以下错误: 达到10个$ digest()迭代。流产! 如果我删除了,那么承诺永远不会得到解决,而测试失败

  • 问题内容: 在我的控制器中,我从另一项服务中获得了承诺。我在其中添加了“ then”子句,但从未调用过“ then”。 看到这个矮人:http ://plnkr.co/edit/dX0Oz1?p=preview (javascript版本) “ fakeLongRunningPromise”会创建一个承诺,该承诺会在2秒后自动解决。 一旦履行了诺言,我便在控制器本身中向控制台发送了一条便条。 我可

  • 问题内容: 我有使用,它可以进行远程调用,并返回promise: 要对我进行单元测试,需要模拟,以便其方法返回promise。这是我的方法: 从上面可以看到,我的模拟的定义取决于,我必须使用来加载。此外,应该在中进行注入模拟,这应该在之前进行。但是,更改模拟后,其值不会更新。 正确的方法是什么? 问题答案: 我不确定为什么您的方法不起作用,但是我通常使用该函数来完成。像这样: 还要记住,您将需要调

  • 问题内容: AngularJS文档说: $ qpromise由模板引擎以角度识别,这意味着在模板中,您可以将附加到作用域的promise视为它们的结果值。 所以有人可以解释一下这种提琴无法正常工作的原因吗?不可能更改文本字段的值。但是分配保证$http服务返回作用域字段的工作就像一个超级按钮。 控制器: HTML: 问题答案: 您需要在promise对象上使用then()函数: 就您而言,我认为您