根据angular.js来源:
$ q promises被模板化引擎识别为angular,这意味着在模板中,您可以将附加到范围的promise视为结果值。
所以,我有一个控制器,它从后端获取一个类别列表,
function myController($scope, $categoryService) {
...
$scope.categoriesList = categoryService.search().then(function(response) {
return response;
}
...
}
在我的模板中,我有一个选择:
<select multiple ng-model="categories" ng-options="category.name for category in categoriesList"></select>
在浏览器中“有效”(选择显示填充的列表)
但是你是如何测试的?
我有以下规格:
it('populates the categoriesList from the categoryService', inject(function(categoryService, $q, $controller, $rootScope) {
var $scope = $rootScope.$new();
var catList = [{id:1, name:"Animal"},{id:2, name:"Vegetable"}];
var deferred = $q.defer()
spyOn(categoryService, 'search').andReturn(deferred.promise);
$controller(myController, {'$scope': $scope});
expect(categoryService.search).toHaveBeenCalled(); // PASSES
deferred.resolve(catList);
$scope.$digest();
expect($scope.categoriesList).toEqual(catList); // FAILS, returns the promise instead
}));
如果我重写了我的初始化程序
...then(function(response) {
$scope.categoriesList = response;
}
我的测试将通过,但后来我没有将范围分配给范围,模板引擎也没有解决对我的承诺。在我看来,第一个实现是框架的意图,但它是不可测试的。第二个实现是可测试的,但不是将数据附加到范围的预期方法。
答案 0 :(得分:1)
当你说
时$scope.categoriesList = categoryService.search().then(function(response) {
return response;
}
$scope.categoriesList
未分配response
;相反,它会被分配一个新的承诺,解析到response
(如您的测试所示)。由于最初的承诺已经解决为response
,您可以拥有:
$scope.categoriesList = categoryService.search()
文档的含义是,您可以将$scope.categoriesList
分配给此类承诺,并且该视图将将表达式categoriesList
视为其解析为的值(在在这种情况下,response
) - 它实际上并不接受该值并将其分配给范围。
[更新]
如果您正在测试控制器,而不是类别服务本身,我会完全保留承诺 - 可能是这样的:
it('populates the categoriesList from the categoryService', inject(function(categoryService, $controller, $rootScope) {
var $scope = $rootScope.$new();
var catList = [{id:1, name:"Animal"},{id:2, name:"Vegetable"}];
spyOn(categoryService, 'search').andReturn(catList);
$controller(myController, {'$scope': $scope});
expect(categoryService.search).toHaveBeenCalled();
$scope.$digest();
expect($scope.categoriesList).toEqual(catList);
}));
答案 1 :(得分:1)
我遇到了同样的问题,最后在我的测试中这样做了:
it("leaves a 'countries' promise that resolves to countries in the scope", function() {
var value = null;
scope.countries.then(function(v) {
value = v;
});
scope.$apply();
expect(value).toEqual([{ Code: "SE", Name: "Sweden" }]);
});
国家而不是类别,但同样的技术应该适用于您的情况。
(我省略了创建范围变量的beforeEach并使用$ httpBackend设置了GET期望,但当然需要它们。)