Angular 测试:我如何测试 angular 中包含 ajax 的承诺?
Angular test: How can I test angular promise with ajax in it?
我如何测试 angular 承诺其中包含 ajax?
代码是通过 ajax 调用父级,然后通过 ajax 调用其余的子级。
代码,
app.controller('MyController', ['$scope', '$http', '$timeout', '$q', function($scope, $http, $timeout, $q) {
$scope.myParen = function(url) {
var deferred = $q.defer();
setTimeout(function() {
$http({
method: 'GET',
url: url
})
.success(function(data, status, headers, config) {
deferred.resolve([data]);
})
.error(function(data, status, headers, config) {
deferred.reject(data);
});
}, 1000);
return deferred.promise;
}
$scope.submit = function() {
$scope.commentCollection = '';
var promise = $scope.myParen('https://example.com/parents/1');
promise.then(function(success) {
var list = success;
$http({
method: 'GET',
url: 'https://example.com/parents/1/children'
})
.success(function(data, status, headers, config) {
$scope.commentCollection = list.concat(data);
})
.error(function(data, status, headers, config) {
$scope.error = data;
});
}, function(error) {
$scope.error = error;
});
};
}]);
测试,
describe('MyController Test', function() {
beforeEach(module('RepoApp'));
var controller, $scope, $http, $httpBackend, $q;
var deferred;
beforeEach(inject(function ($rootScope, $controller, $http, $httpBackend, $q) {
$scope = $rootScope.$new();
deferred = $q.defer();
// Create the controller.
controller = $controller;
controller("MyController", {$scope, $http, $httpBackend, $q});
}));
it('should demonstrate using when (200 status)', inject(function($rootScope, $http, $httpBackend, $q) {
var $scope = {};
/* Code Under Test */
$scope.myParen = function(url) {
...
}
$scope.submit = function() {
...
};
/* End */
$scope.submit();
deferred.promise.then(function (value) {
$httpBackend.whenGET('https://example.com/parents/1/children', undefined, {})
.respond(function(){ return [200,{foo: 'bar'}]});
expect(value).toBe(4);
});
deferred.resolve(4);
$rootScope.$apply();
expect($scope.commentCollection).toEqual({foo: 'bar'});
}));
});
失败的结果,
Expected '' to equal { foo: 'bar' }.
有什么想法吗?
编辑:
....
deferred.resolve(4);
$rootScope.$apply();
$timeout.flush();
expect($scope.commentCollection).toEqual({foo: 'bar'});
Re-write 您的 $scope.myParen
函数使用 $timeout
而不是 setTimeout
。
$scope.myParen = function(url) {
var promise = $http({
method: 'GET',
url: url
})
.then (function(response) {
var data = response.data;
return $timeout(function(){return data;}, 1000);
})
.catch(function(response) {
var data = response.data;
return
($timeout(angular.noop, 1000)
).then (function () {
throw data;
});
});
return promise;
}
然后在测试中你可以使用$timeout.flush()
同步刷新延迟函数的队列。
Deprecation Notice
The $http legacy promise methods success
and error
have been deprecated. Use the standard then
method instead.
-- AngularJS $http Service API Reference -- deprecation notice
1) 在控制器
中将 setTimeout
切换为 $timeout
2) 替换beforeEach
函数中的所有$httpBackend
3) 使用 .flush()
函数
describe('MyController Test', function() {
beforeEach(module('app'));
var controller, $scope, $http, httpBackend, $q;
var deferred;
beforeEach(inject(function ($rootScope, $controller, $http, $httpBackend, $q) {
$httpBackend
.whenGET('https://example.com/parents/1', undefined, {})
.respond(function(){ return [200, {parents: []}]});
$httpBackend
.whenGET('https://example.com/parents/1/children', undefined, {})
.respond(function(){ return [200, {foo: 'bar'}]});
$scope = $rootScope.$new();
deferred = $q.defer();
// Create the controller.
controller = $controller;
controller("MyController", {$scope: $scope, $http: $http, $httpBackend: $httpBackend, $q: $q});
}));
it('should demonstrate using when (200 status)', inject(function($httpBackend, $timeout) {
// var $scope = {}; // don't write it, becouse you rewrite a scope which defined at beforeEach function
$scope.submit();
//$httpBackend.flush(); // wait when backend return parents
$timeout.flush(); // wait timeout in $scope.myParen
$httpBackend.flush(); // wait when backend return children
expect($scope.commentCollection[0]).toEqual({parents: []});
expect($scope.commentCollection[1]).toEqual({foo: 'bar'});
}));
});
我如何测试 angular 承诺其中包含 ajax?
代码是通过 ajax 调用父级,然后通过 ajax 调用其余的子级。
代码,
app.controller('MyController', ['$scope', '$http', '$timeout', '$q', function($scope, $http, $timeout, $q) {
$scope.myParen = function(url) {
var deferred = $q.defer();
setTimeout(function() {
$http({
method: 'GET',
url: url
})
.success(function(data, status, headers, config) {
deferred.resolve([data]);
})
.error(function(data, status, headers, config) {
deferred.reject(data);
});
}, 1000);
return deferred.promise;
}
$scope.submit = function() {
$scope.commentCollection = '';
var promise = $scope.myParen('https://example.com/parents/1');
promise.then(function(success) {
var list = success;
$http({
method: 'GET',
url: 'https://example.com/parents/1/children'
})
.success(function(data, status, headers, config) {
$scope.commentCollection = list.concat(data);
})
.error(function(data, status, headers, config) {
$scope.error = data;
});
}, function(error) {
$scope.error = error;
});
};
}]);
测试,
describe('MyController Test', function() {
beforeEach(module('RepoApp'));
var controller, $scope, $http, $httpBackend, $q;
var deferred;
beforeEach(inject(function ($rootScope, $controller, $http, $httpBackend, $q) {
$scope = $rootScope.$new();
deferred = $q.defer();
// Create the controller.
controller = $controller;
controller("MyController", {$scope, $http, $httpBackend, $q});
}));
it('should demonstrate using when (200 status)', inject(function($rootScope, $http, $httpBackend, $q) {
var $scope = {};
/* Code Under Test */
$scope.myParen = function(url) {
...
}
$scope.submit = function() {
...
};
/* End */
$scope.submit();
deferred.promise.then(function (value) {
$httpBackend.whenGET('https://example.com/parents/1/children', undefined, {})
.respond(function(){ return [200,{foo: 'bar'}]});
expect(value).toBe(4);
});
deferred.resolve(4);
$rootScope.$apply();
expect($scope.commentCollection).toEqual({foo: 'bar'});
}));
});
失败的结果,
Expected '' to equal { foo: 'bar' }.
有什么想法吗?
编辑:
....
deferred.resolve(4);
$rootScope.$apply();
$timeout.flush();
expect($scope.commentCollection).toEqual({foo: 'bar'});
Re-write 您的 $scope.myParen
函数使用 $timeout
而不是 setTimeout
。
$scope.myParen = function(url) {
var promise = $http({
method: 'GET',
url: url
})
.then (function(response) {
var data = response.data;
return $timeout(function(){return data;}, 1000);
})
.catch(function(response) {
var data = response.data;
return
($timeout(angular.noop, 1000)
).then (function () {
throw data;
});
});
return promise;
}
然后在测试中你可以使用$timeout.flush()
同步刷新延迟函数的队列。
Deprecation Notice
The $http legacy promise methods
success
anderror
have been deprecated. Use the standardthen
method instead.-- AngularJS $http Service API Reference -- deprecation notice
1) 在控制器
中将setTimeout
切换为 $timeout
2) 替换beforeEach
函数中的所有$httpBackend
3) 使用 .flush()
函数
describe('MyController Test', function() {
beforeEach(module('app'));
var controller, $scope, $http, httpBackend, $q;
var deferred;
beforeEach(inject(function ($rootScope, $controller, $http, $httpBackend, $q) {
$httpBackend
.whenGET('https://example.com/parents/1', undefined, {})
.respond(function(){ return [200, {parents: []}]});
$httpBackend
.whenGET('https://example.com/parents/1/children', undefined, {})
.respond(function(){ return [200, {foo: 'bar'}]});
$scope = $rootScope.$new();
deferred = $q.defer();
// Create the controller.
controller = $controller;
controller("MyController", {$scope: $scope, $http: $http, $httpBackend: $httpBackend, $q: $q});
}));
it('should demonstrate using when (200 status)', inject(function($httpBackend, $timeout) {
// var $scope = {}; // don't write it, becouse you rewrite a scope which defined at beforeEach function
$scope.submit();
//$httpBackend.flush(); // wait when backend return parents
$timeout.flush(); // wait timeout in $scope.myParen
$httpBackend.flush(); // wait when backend return children
expect($scope.commentCollection[0]).toEqual({parents: []});
expect($scope.commentCollection[1]).toEqual({foo: 'bar'});
}));
});