如何编写http请求的单元测试?
How to write unit test for http request?
我正在尝试对我的服务进行单元测试
在我的测试控制器中
myService.getItem('/api/toy/' + scope.id).success(
function(toy) {
$scope.toy = toys.details;
}
);
我的服务
angular.module('toyApp').service('myService', ['$http',
function($http) {
var service = {};
return {
getItem: function(url) {
return $http.get(url);
},
};
}
]);
测试文件。
describe('toy ctrl', function () {
var $httpBackend, ctrl, myService;
beforeEach(module('toyApp'));
beforeEach(inject(function (_$controller_, _$httpBackend_, _$rootScope_, __myService_) {
scope = _$rootScope_.$new();
$httpBackend = _$httpBackend_;
myService = _myService_;
ctrl = _$controller_('toyCtrl', {
$scope: scope
});
}));
describe('call my service', function() {
it('should make request when app loads', function() {
$httpBackend.expectGET('/api/toy/123').respond({id:123, detail:456 });
myService.getItem('/api/toy/123').then(function(toy){
expect(scope.toy.detail).toBe(456);
})
$httpBackend.flush();
})
})
我得到
Error: Unexpected request: GET /api/toy/123
No more request expected
如果我取出 $httpBackend.flush()
,错误消失但它不会覆盖
function(toy) {
$scope.toy = toys.details;
}
部分。我想涵盖函数调用但不确定如何执行此操作。谁能帮我解决这个问题?
非常感谢
好像您是在"unit"测试控制器,所以您不必引入图片中的服务,因为您只需要测试控制器逻辑。您可以创建模拟服务并在测试中创建控制器时注入它。
示例:
var mockItem = {details:{//somestuff}, id:'1'};// set up a mock object to test against later
//....
beforeEach(inject(function (_$controller_, _$httpBackend_, _$rootScope_, _$q_) {
scope = _$rootScope_.$new();
$httpBackend = _$httpBackend_;
//Set up mock
myService = jasmine.CreateSpyObj('myService', ['getItem']);
myService.getItem.and.returnValue($q.when(mockItem ));
ctrl = _$controller_('toyCtrl', {
$scope: scope,
myService: myService //<-- Pass it here
});
}));
//.....Assuming you are making the call when controller is instantiated
it('should make request when app loads', function() {
expect(myService.getItem).toHaveBeenCalled();
//You could also check as below
//expect(myService.getItem).toHaveBeenCalledWith(expectedidpassedin);
scope.$digest(); //Resolve $q promise callback
expect($scope.toy).toEqual(mockItem .details);
});
如果您专门单独对您的服务进行单元测试,您可以这样做:
it('should make request when app loads', function() {
var resp;
$httpBackend.expectGET('/api/toy/123').respond({id:123, detail:456});
myService.getItem('/api/toy/123').then(function(response){
resp = response.data;
});
$httpBackend.flush();
expect(resp.detail).toEqual(456);
});
在您的控制器中而不是链接 success
使用 then
myService.getItem('/api/toy/' + scope.id).then(
function(response) {
$scope.toy = response.toys.details;
});
我正在尝试对我的服务进行单元测试
在我的测试控制器中
myService.getItem('/api/toy/' + scope.id).success(
function(toy) {
$scope.toy = toys.details;
}
);
我的服务
angular.module('toyApp').service('myService', ['$http',
function($http) {
var service = {};
return {
getItem: function(url) {
return $http.get(url);
},
};
}
]);
测试文件。
describe('toy ctrl', function () {
var $httpBackend, ctrl, myService;
beforeEach(module('toyApp'));
beforeEach(inject(function (_$controller_, _$httpBackend_, _$rootScope_, __myService_) {
scope = _$rootScope_.$new();
$httpBackend = _$httpBackend_;
myService = _myService_;
ctrl = _$controller_('toyCtrl', {
$scope: scope
});
}));
describe('call my service', function() {
it('should make request when app loads', function() {
$httpBackend.expectGET('/api/toy/123').respond({id:123, detail:456 });
myService.getItem('/api/toy/123').then(function(toy){
expect(scope.toy.detail).toBe(456);
})
$httpBackend.flush();
})
})
我得到
Error: Unexpected request: GET /api/toy/123
No more request expected
如果我取出 $httpBackend.flush()
,错误消失但它不会覆盖
function(toy) {
$scope.toy = toys.details;
}
部分。我想涵盖函数调用但不确定如何执行此操作。谁能帮我解决这个问题? 非常感谢
好像您是在"unit"测试控制器,所以您不必引入图片中的服务,因为您只需要测试控制器逻辑。您可以创建模拟服务并在测试中创建控制器时注入它。
示例:
var mockItem = {details:{//somestuff}, id:'1'};// set up a mock object to test against later
//....
beforeEach(inject(function (_$controller_, _$httpBackend_, _$rootScope_, _$q_) {
scope = _$rootScope_.$new();
$httpBackend = _$httpBackend_;
//Set up mock
myService = jasmine.CreateSpyObj('myService', ['getItem']);
myService.getItem.and.returnValue($q.when(mockItem ));
ctrl = _$controller_('toyCtrl', {
$scope: scope,
myService: myService //<-- Pass it here
});
}));
//.....Assuming you are making the call when controller is instantiated
it('should make request when app loads', function() {
expect(myService.getItem).toHaveBeenCalled();
//You could also check as below
//expect(myService.getItem).toHaveBeenCalledWith(expectedidpassedin);
scope.$digest(); //Resolve $q promise callback
expect($scope.toy).toEqual(mockItem .details);
});
如果您专门单独对您的服务进行单元测试,您可以这样做:
it('should make request when app loads', function() {
var resp;
$httpBackend.expectGET('/api/toy/123').respond({id:123, detail:456});
myService.getItem('/api/toy/123').then(function(response){
resp = response.data;
});
$httpBackend.flush();
expect(resp.detail).toEqual(456);
});
在您的控制器中而不是链接 success
使用 then
myService.getItem('/api/toy/' + scope.id).then(
function(response) {
$scope.toy = response.toys.details;
});