gpt4 book ai didi

javascript - 我如何模拟 AngularJS 单元测试中 promise 的结果?

转载 作者:数据小太阳 更新时间:2023-10-29 04:14:50 26 4
gpt4 key购买 nike

我的 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' 不是一个对象(评估 '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;
});

关于javascript - 我如何模拟 AngularJS 单元测试中 promise 的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21948459/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com