如何使用 httpbackend 测试 Restangular http 调用以测试成功和错误情况?
How to Karma test Restangular http call using httpbackend to test both success and error cases?
我正在使用 karma/jasmine 测试 angular 服务,我的服务功能之一如下。我需要达到 100% 的覆盖率,但似乎无法弄清楚如何测试成功和错误情况..
function getAccount(accountId) {
var defer = $q.defer(), myService;
myService = Restangular.all('Some/Url/Path');
myService.get('', {}, {
'header-info': 'bla'
})
.then(function onSuccess(response) {
defer.resolve(response);
}, function onError() {
someMethodCall();
});
return defer.promise;
}
在我对应的 .spec 测试文件中,我有:
it('should succeed in getting account', function() {
httpBackend.whenGET('Some/Url/Path').respond(200, mockResponse);
var promise = myServices.getAccount('account123');
promise.then(function(response) {
expect(response).toEqual(mockResponse);
});
it('should error out in getting account', function() {
httpBackend.whenGET('Some/Url/Path').respond(500, '');
var promise = myServices.getAccount('account123');
promise.then(function() {
expect(someMethodCall).toHaveBeenCalled();
});
现在,两种情况 "pass",但我没有得到 onError 情况的分支覆盖。 onSuccess 案例的传递似乎有些可疑。
基本上我问的是编写测试用例的正确语法和方法是什么,这样当我对我的 API[= 进行 200 和 500 调用时,我可以成功和错误情况12=]
由于您的服务中没有对 $http
的任何调用,我建议您模拟 Restangular
而不是使用 httpBackend
。这样,您的测试就不必了解 Restangular
的实现细节,除了 returns,就像您的服务一样。
模拟示例:
var Restangular = {
all: function() {
return {
get: function() {
restangularDeferred = $q.defer();
return restangularDeferred.promise;
}
};
}
};
现在您可以轻松解决或拒绝 restangularDeferred
,具体取决于您要测试的内容。
设置您的模块以使用模拟:
module('myApp', function($provide) {
$provide.value('Restangular', Restangular);
});
成功案例测试示例:
it('success', function() {
// If you want you can still spy on the mock
spyOn(Restangular, 'all').and.callThrough();
var mockResponse = {};
var promise = myServices.getAccount('account123');
promise.then(function(response) {
expect(response).toEqual(mockResponse);
expect(Restangular.all).toHaveBeenCalledWith('Some/Url/Path');
});
restangularDeferred.resolve(mockResponse);
// Trigger the digest loop and resolution of promise callbacks
$rootScope.$digest();
});
错误案例测试示例:
it('error', function() {
spyOn(anotherService, 'someMethodCall');
var mockResponse = {};
myServices.getAccount('acount123');
restangularDeferred.reject(mockResponse);
$rootScope.$digest();
expect(anotherService.someMethodCall).toHaveBeenCalled();
});
请注意,我在示例中将 someMethodCall
移到了 anotherService
。
我正在使用 karma/jasmine 测试 angular 服务,我的服务功能之一如下。我需要达到 100% 的覆盖率,但似乎无法弄清楚如何测试成功和错误情况..
function getAccount(accountId) {
var defer = $q.defer(), myService;
myService = Restangular.all('Some/Url/Path');
myService.get('', {}, {
'header-info': 'bla'
})
.then(function onSuccess(response) {
defer.resolve(response);
}, function onError() {
someMethodCall();
});
return defer.promise;
}
在我对应的 .spec 测试文件中,我有:
it('should succeed in getting account', function() {
httpBackend.whenGET('Some/Url/Path').respond(200, mockResponse);
var promise = myServices.getAccount('account123');
promise.then(function(response) {
expect(response).toEqual(mockResponse);
});
it('should error out in getting account', function() {
httpBackend.whenGET('Some/Url/Path').respond(500, '');
var promise = myServices.getAccount('account123');
promise.then(function() {
expect(someMethodCall).toHaveBeenCalled();
});
现在,两种情况 "pass",但我没有得到 onError 情况的分支覆盖。 onSuccess 案例的传递似乎有些可疑。
基本上我问的是编写测试用例的正确语法和方法是什么,这样当我对我的 API[= 进行 200 和 500 调用时,我可以成功和错误情况12=]
由于您的服务中没有对 $http
的任何调用,我建议您模拟 Restangular
而不是使用 httpBackend
。这样,您的测试就不必了解 Restangular
的实现细节,除了 returns,就像您的服务一样。
模拟示例:
var Restangular = {
all: function() {
return {
get: function() {
restangularDeferred = $q.defer();
return restangularDeferred.promise;
}
};
}
};
现在您可以轻松解决或拒绝 restangularDeferred
,具体取决于您要测试的内容。
设置您的模块以使用模拟:
module('myApp', function($provide) {
$provide.value('Restangular', Restangular);
});
成功案例测试示例:
it('success', function() {
// If you want you can still spy on the mock
spyOn(Restangular, 'all').and.callThrough();
var mockResponse = {};
var promise = myServices.getAccount('account123');
promise.then(function(response) {
expect(response).toEqual(mockResponse);
expect(Restangular.all).toHaveBeenCalledWith('Some/Url/Path');
});
restangularDeferred.resolve(mockResponse);
// Trigger the digest loop and resolution of promise callbacks
$rootScope.$digest();
});
错误案例测试示例:
it('error', function() {
spyOn(anotherService, 'someMethodCall');
var mockResponse = {};
myServices.getAccount('acount123');
restangularDeferred.reject(mockResponse);
$rootScope.$digest();
expect(anotherService.someMethodCall).toHaveBeenCalled();
});
请注意,我在示例中将 someMethodCall
移到了 anotherService
。