【发布时间】:2014-06-04 03:50:33
【问题描述】:
我正在为使用 Promise 的控制器编写一些单元测试。 基本上是这样的:
UserService.getUser($routeParams.contactId).then(function (data) {
$scope.$apply(function () {
$scope.contacts = data;
});
});
我嘲笑了我的 UserService。这是我的单元测试:
beforeEach(inject(function ($rootScope, $controller, $q, $routeParams) {
$routeParams.contactId = contactId;
window.localStorage.clear();
UserService = {
getUser: function () {
def = $q.defer();
return def.promise;
}
};
spyOn(UserService, 'getUser').andCallThrough();
scope = $rootScope.$new();
ctrl = $controller('ContactDetailController', {
$scope: scope,
UserService:UserService
});
}));
it('should return 1 contact', function () {
expect(scope.contacts).not.toBeDefined();
def.resolve(contact);
scope.$apply();
expect(scope.contacts.surname).toEqual('NAME');
expect(scope.contacts.email).toEqual('EMAIL');
});
这给了我以下错误:
Error: [$rootScope:inprog] $digest already in progress
现在删除控制器中的 $scope.$apply 会导致测试通过,如下所示:
UserService.getUser($routeParams.contactId).then(function (data) {
$scope.contacts = data;
});
但是这会破坏我的控制器的功能......那么我应该在这里做什么?
感谢您的回复,用户服务中没有发生 $apply。它在控制器中。像这样:
编辑: $apply 就是这样在控制器中发生的。
appController.controller('ContactDetailController', function ($scope, $routeParams, UserService) {
UserService.getUser($routeParams.contactId).then(function (data) {
$scope.$apply(function () {
$scope.contacts = data;
});
});
真实用户服务:
function getUser(user) {
if (user === undefined) {
user = getUserId();
}
var deferred = Q.defer();
$http({
method: 'GET',
url: BASE_URL + '/users/' + user
}).success(function (user) {
deferred.resolve(user);
});
return deferred.promise;
}
【问题讨论】:
-
测试 Promise 时需要手动运行摘要。
-
是的,您应该在单元测试中手动运行摘要,并且您可能不应该在您的服务中这样做。为什么你的服务有 $scope?服务应该充当模型,控制器应该从服务中获取数据。如果你发现你需要在你的代码中运行 $apply,那么可能有些地方不对。
-
作用域上的 $apply 发生在控制器中。很抱歉造成混淆,请参阅上面帖子中的编辑。
-
UserService中可能存在问题,因为它解决了$digest循环之外的承诺。你能发布它如何获取用户并解决它返回的承诺的代码/细节吗? -
@MichalCharemza 已将其添加到上面的帖子中
标签: javascript angularjs unit-testing promise q