2016-09-01 50 views
0

为什么在测试用例中要执行$scope.$apply()才能完成异步处理。

说,我有一个服务

angular.service("a",function($q){ 
    return { 
     getValue: function(){ 
      return $q.resolve(someObj) 
     } 
    } 
}) 

而且在我的测试

it("test this",function(done){ 
    a.getValue() 
    .then(function(data){ 
     expect(data).toEqual(data) 
     done(); 
    }) 
    $scope.$apply(); 
}) 

回答

3

这引发消化周期。

docs

测试时的承诺,它知道的 承诺的分辨率是联系在一起的消化周期是非常重要的。这意味着一个承诺,然后 捕获和最终回调函数仅在摘要 已运行后调用。在测试中,您可以通过调用示波器的 $ apply函数来触发摘要。如果您的测试中没有示波器,您可以通过 注入$ rootScope并在其上调用$ apply。

对于http调用,您使用$ httpBackend.flush()。从docs

的$ httpBackend在生产中使用总是响应异步请求 。如果我们在单元测试中保留了这种行为,我们 必须创建难以编写的异步单元测试,以跟踪 并进行维护。但是测试模拟也不能同步响应 ;这将改变被测代码的执行。 因此,模拟$ httpBackend有一个flush()方法,该方法允许测试显式刷新挂起的请求。这保留了 后端的异步api,同时允许测试同步执行 。

+0

感谢您的回答@scott 您能否详细说明为什么承诺要求在我没有更改范围上的任何内容时运行摘要循环。 –

+0

从这个[post](http://blog.xebia.com/testing-promises-in-angularjs/):当一个承诺解决了,它的回调不立即被调用。相反,Angular将promise.resolve回调放在evalAsync队列中。他们在那里等待队列将被处理。只有这样才会调用回调。它是处理队列的digest()方法。 – ScottL