我在使用Chrome在Karma中运行我的一个AngularJS测试时遇到问题。该测试适用于PhantomJS。
使用Chrome运行测试时出现以下错误:
Chrome 46.0.2490 (Windows 7 0.0.0) ERROR
Uncaught Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.3.18/$rootScope/inprog?p0=%24digest
at C:/dev/unionvms_eu/branches/dev/unionvms-web/bower_components/angular-mocks/angular-mocks.js:275
测试
describe('todoRestService', function() {
beforeEach(module('todoApp'));
//MOCK RESOURCE
beforeEach(function () {
var mockResource = {
todo: function() {
return {
update: function(todoDTO, callback) {
callback({
code : 200,
data: {
status : 'CLOSED'
}
});
},
}
},
};
module(function ($provide) {
$provide.value('todoRestFactory', mockResource);
});
});
it("updateTodoStatus should send request to backend and return received object", inject(function($rootScope, $log, todoRestService, Todo) {
var todo = new Todo();
todo.status = "CLOSED";
var resolved = false;
$rootScope.$apply(function(){
todoRestService.updateTodoStatus(todo).then(function(updatedTodo){
resolved = true;
expect(updatedTodo.status).toEqual(todo.status);
});
});
$rootScope.$digest();
expect(resolved).toBe(true);
}));
});
代码:
angular.module('todoApp')
.factory('todoRestFactory',function($resource) {
return {
todo : function(){
return $resource('/app/todo', {}, {
update: {method: 'PUT'}
});
},
};
})
.factory('todoRestService', function($q, $log, todoRestFactory, Todo){
var updateTodoStatus = function(todo){
var deferred = $q.defer();
todoRestFactory.todo().update(todo.DTO(), function(response) {
if(response.code !== 200){
deferred.reject("Invalid response status");
return;
}
deferred.resolve(Todo.fromDTO(response.data));
}, function(error) {
$log.error("Error updating todo status");
$log.error(error);
deferred.reject(error);
});
return deferred.promise;
};
return {
updateTodoStatus: updateTodoStatus,
};
});
如果我从测试中删除$rootScope.$digest();
,则错误消失,但最后一个断言将失败。我该如何进行测试?
答案 0 :(得分:0)
您需要检查$ digest是否已经开始。 你可以通过
来做到这一点 if(!$scope.$$phase) {
//do smth here
}
答案 1 :(得分:0)
我认为有3种方法可以解决这个问题:
编写一个看起来像这样的safeApply函数:
$scope.safeApply = function(fn) { var phase = this.$root.$$phase; if(phase === '$apply' || phase === '$digest') { if(fn && (typeof(fn) === 'function')) { fn(); } } else { this.$apply(fn); } };
您还可以使用safeApply组件
在代码中:
$scope.$safeApply();
拨打$apply
内的$timeout
:
$timeout($scope.$apply, 0);