AngularJS 使用 httpBackend 的 Jasmine 单元测试 - rootScope 变量未定义
AngularJS Jasmine unit test with httpBackend - rootScope variable is undefined
我有以下控制器
app.controller('NavController', ['$rootScope', '$scope', 'api', function($rootScope, $scope, $location, auth, api) {
$scope.load = function() {
return api.get('/location').success(function(data) {
$rootScope.locations = data;
}).error(function(data) {
console.log('load error');
});
};
}]);
这是我为它编写的单元测试
describe('Navigation Controller Test', function() {
beforeEach(module('app'));
var controller, scope, rootScope, httpBackend;
beforeEach(inject(function(_$controller_, _$rootScope_, $httpBackend) {
var $controller = _$controller_;
rootScope = _$rootScope_;
scope = rootScope.$new();
httpBackend = $httpBackend;
controller = $controller('NavController', {
$rootScope: rootScope,
$scope: scope,
});
apiRequestHandler = httpBackend.when('GET', '/api/v2/location')
.respond({userId: 'userX'});
}));
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
describe('load()', function() {
it('should have locations when successful', function() {
httpBackend.expectGET('/api/v2/location');
scope.load();
expect(rootScope.locations).toEqual("{userId: 'userX'}");
httpBackend.flush();
});
});
});
我目前遇到的问题是 rootScope.locations
即使在调用 scope.load()
函数后仍未定义。我不太确定为什么会这样,但我似乎找到的最接近 post 的是 this,我认为它可能与我的问题有关,但我不太确定。
当 get 请求成功时,我在控制器中做了一个 console.log($rootScope.locations)
,它有正确的输出,但是我不知道如何让它在这个测试中看起来相同。
你不应该乱用控制器中的 rootScope。你的控制器应该只与 $scope 一起工作,为了让茉莉花测试工作,你应该有 beforeEach 如下:
var controller, scope, httpBackend;
beforeEach(inject(function(_$controller_, _$rootScope_, $httpBackend) {
var $controller = _$controller_;
scope = rootScope.$new();
httpBackend = $httpBackend;
controller = $controller('NavController', {
$scope: scope,
//authentication dependency and so on
});
...
}));
你是控制器:
app.controller('NavController', function($scope, api) {
$scope.load = function() {
return api.get('/location').success(function(data) {
$scope.locations = data;
}).error(function(data) {
console.log('load error');
});
};
});
编辑:
另外测试流程应该是:
it('should have locations when successful', function() {
scope.load();
httpBackend.expectGET('/api/v2/location');
httpBackend.flush();
expect(rootScope.locations).toEqual("{userId: 'userX'}");
});
您需要首先调用您的函数,而不是对 http 后端、下一次刷新和仅在之后进行验证有期望。此外,仅当您在控制器中使用 $http 时才能使用 httpBackend,而不是其他第三方 ajax 调用提供程序。
我有以下控制器
app.controller('NavController', ['$rootScope', '$scope', 'api', function($rootScope, $scope, $location, auth, api) {
$scope.load = function() {
return api.get('/location').success(function(data) {
$rootScope.locations = data;
}).error(function(data) {
console.log('load error');
});
};
}]);
这是我为它编写的单元测试
describe('Navigation Controller Test', function() {
beforeEach(module('app'));
var controller, scope, rootScope, httpBackend;
beforeEach(inject(function(_$controller_, _$rootScope_, $httpBackend) {
var $controller = _$controller_;
rootScope = _$rootScope_;
scope = rootScope.$new();
httpBackend = $httpBackend;
controller = $controller('NavController', {
$rootScope: rootScope,
$scope: scope,
});
apiRequestHandler = httpBackend.when('GET', '/api/v2/location')
.respond({userId: 'userX'});
}));
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
describe('load()', function() {
it('should have locations when successful', function() {
httpBackend.expectGET('/api/v2/location');
scope.load();
expect(rootScope.locations).toEqual("{userId: 'userX'}");
httpBackend.flush();
});
});
});
我目前遇到的问题是 rootScope.locations
即使在调用 scope.load()
函数后仍未定义。我不太确定为什么会这样,但我似乎找到的最接近 post 的是 this,我认为它可能与我的问题有关,但我不太确定。
当 get 请求成功时,我在控制器中做了一个 console.log($rootScope.locations)
,它有正确的输出,但是我不知道如何让它在这个测试中看起来相同。
你不应该乱用控制器中的 rootScope。你的控制器应该只与 $scope 一起工作,为了让茉莉花测试工作,你应该有 beforeEach 如下:
var controller, scope, httpBackend;
beforeEach(inject(function(_$controller_, _$rootScope_, $httpBackend) {
var $controller = _$controller_;
scope = rootScope.$new();
httpBackend = $httpBackend;
controller = $controller('NavController', {
$scope: scope,
//authentication dependency and so on
});
...
}));
你是控制器:
app.controller('NavController', function($scope, api) {
$scope.load = function() {
return api.get('/location').success(function(data) {
$scope.locations = data;
}).error(function(data) {
console.log('load error');
});
};
});
编辑: 另外测试流程应该是:
it('should have locations when successful', function() {
scope.load();
httpBackend.expectGET('/api/v2/location');
httpBackend.flush();
expect(rootScope.locations).toEqual("{userId: 'userX'}");
});
您需要首先调用您的函数,而不是对 http 后端、下一次刷新和仅在之后进行验证有期望。此外,仅当您在控制器中使用 $http 时才能使用 httpBackend,而不是其他第三方 ajax 调用提供程序。