我的CompanyService
是:
angular.module('mean').service('CompanyService', ['$http', '$rootScope', '$q', function($http, $rootScope, $q) {
var company = this;
var initializedDeferred = $q.defer();
company.company_data = {}
company.initialized = initializedDeferred.promise;
company.getCompany = function() {
return company.company_data;
}
company.get = function (company_id) {
return $http({
url: '/api/v1/company/' + company_id,
method: 'GET',
headers: {
api_key: $rootScope.api_key
}
}).success(function(response) {
if(response.status === 'ok') {
company.company_data = response.company;
initializedDeferred.resolve();
} else {
alert('TBD: Need fail case');
}
});
};
}]);
我的 Controller 是:
angular.module('mean').controller('LocationController', ['$scope', '$location', '$rootScope', 'LocationService', 'UserService', 'CompanyService', '$modal', '$routeParams', function ($scope, $location, $rootScope, LocationService, UserService, CompanyService, $modal, $routeParams) {
$rootScope.menuItem = 'locations';
$scope.contentTemplate = '/views/location/index.html';
$scope.locations = [];
$scope.current_location = null;
$scope.newLocation = {};
$scope.location_parent_id = $routeParams.location_parent_id;
$scope.index = function() {
CompanyService.initialized.then(function() {
$scope.test = 'a';
var company_id = CompanyService.getCompany()._id;
LocationService.list(company_id, $routeParams.location_parent_id).then(function(response) {
if(response.data.status === 'ok') {
$scope.locations = response.data.locations;
$scope.current_location = response.data.location || null;
}
});
});
}
$scope.addLocationModal = function() {
$scope.location_types = ['warehouse', 'section', 'row', 'shelf', 'bin'];
$modal({
scope: $scope,
template: '/views/location/addLocationModal.html',
show: true,
animation: 'am-fade-and-scale'
});
}
$scope.createLocation = function() {
$scope.newLocation.company_id = CompanyService.getCompany()._id;
LocationService.create($scope.newLocation).then(function(response) {
if(response.data.status === 'ok') {
$scope.$hide();
} else {
alert('TBD');
}
});
}
}]);
我的测试是:
(function() {
describe('LocationController', function() {
var $scope, $location, $rootScope, $modal, deferred, CompanyService, createController;
beforeEach(module('mean'));
beforeEach(inject(function($injector) {
$location = $injector.get('$location');
$rootScope = $injector.get('$rootScope');
$modal = $injector.get('$modal');
$scope = $rootScope.$new();
var $controller = $injector.get('$controller');
var $q = $injector.get('$q');
var params = {
'$scope': $scope,
CompanyService: jasmine.createSpyObj('CompanyService', ['initialized'])
}
params.CompanyService.initialized.andCallFake(function () {
deferred = $q.defer();
return deferred.promise;
});
createController = function() {
return $controller('LocationController', params);
};
}));
it('should instantiate initial variables at the top level', function() {
var controller = createController();
$location.path('/company/locations');
expect($location.path()).toBe('/company/locations');
expect($rootScope.menuItem).toBe('locations');
expect($scope.contentTemplate).toBe('/views/location/index.html');
expect($scope.locations.length).toEqual(0);
expect($scope.current_location).toBeNull();
expect($scope.newLocation).toBeDefined();
expect($scope.location_parent_id).not.toBeDefined();
});
it('should list all locations for this company', function() {
var controller = createController();
deferred.resolve();
$scope.index();
expect($scope.test).toBe('a');
});
});
})();
但是,
resolve
无法正常工作。我收到此错误:TypeError: 'undefined' is not an object (evaluating 'deferred.resolve')
有什么帮助吗?
最佳答案
在测试中,您使用伪造的CompanyService.initialized
函数创建延迟对象。但是,仅当您调用$scope.index();
时才调用此函数,该命令在deferred.resolve();
行之后执行。以下应该工作:
it('should list all locations for this company', function() {
var controller = createController();
$scope.index(); // Should in turn call the fake CompanyService.initialized function that creates deferred
deferred.resolve();
$scope.$apply(); // Fire $digest cycle to dispatch promises.
expect($scope.test).toBe('a');
});
更新
Jasmine 不支持监视不是功能的属性。因此,您的 spy 设置无效,因为
CompanyService.initialized
是对象而不是函数,因此andCallFake
无法正常工作。解决方法是在CompanyService
中引入getter函数,例如:company.isInitialized(){ return company.initialized; }
然后在您的 Controller 内部使用此getter函数代替:
$scope.index = function() {
CompanyService.isInitialized().then(function() {
$scope.test = 'a';
// Removed for brevity
});
}
最后更新您的测试代码初始化:
var params = {
'$scope': $scope,
CompanyService: jasmine.createSpyObj('CompanyService', ['isInitialized'])
}
params.CompanyService.isInitialized.andCallFake(function () {
deferred = $q.defer();
return deferred.promise;
});