【发布时间】:2015-09-21 16:27:55
【问题描述】:
我有一个具有以下方法的服务(以及其他方法),它返回一个 $http 承诺
function sessionService($http, serviceRoot) {
return {
getAvailableDates: function () {
return $http.get(serviceRoot + '/session/available_dates');
}
};
};
angular.module('app').service('sessionService', ['$http', 'serviceRoot', sessionService]);
然后是另一个工厂,它有点包装它并将数据缓存/添加到 localStorage。这会返回一个常规的承诺
angular.module('app')
.factory('AvailableDates', AvailableDates);
AvailableDates.$inject = ['sessionService', '$window', '$q'];
function AvailableDates(sessionService, $window, $q) {
var availableDates = [];
return {
getAvailableDates: getAvailableDates
};
function getAvailableDates() {
var deferred = $q.defer();
var fromStorage = JSON.parse($window.sessionStorage.getItem('validDates'));
if (availableDates.length > 0) {
deferred.resolve(availableDates);
} else if (fromStorage !== null) {
deferred.resolve(fromStorage);
} else {
sessionService.getAvailableDates()
.success(function (result) {
availableDates = result;
$window.sessionStorage.setItem('validDates', JSON.stringify(availableDates));
deferred.resolve(availableDates);
});
}
return deferred.promise;
}
}
这一切都很好。我的问题是在模拟 sessionService 时我不知道如何测试这个东西。我已经阅读了所有相关的 stackoverflow 问题,并尝试了各种不同的方法,但均无济于事。
这是我的测试目前的样子:
describe('testing AvailableDates factory', function () {
var mock, service, rootScope, spy, window, sessionStorageSpy, $q;
var dates = [ "2014-09-27", "2014-09-20", "2014-09-13", "2014-09-06", "2014-08-30" ];
var result;
beforeEach(module('app'));
beforeEach(function() {
return angular.mock.inject(function (_sessionService_, _AvailableDates_, _$rootScope_, _$window_, _$q_) {
mock = _sessionService_;
service = _AvailableDates_;
rootScope = _$rootScope_;
window = _$window_;
$q = _$q_;
});
});
beforeEach(inject(function () {
// my service under test calls this service method
spy = spyOn(mock, 'getAvailableDates').and.callFake(function () {
return {
success: function () {
return [ "2014-09-27", "2014-09-20", "2014-09-13", "2014-09-06", "2014-08-30" ];
},
error: function() {
return "error";
}
};
});
spyOn(window.sessionStorage, "getItem").and.callThrough();
}));
beforeEach(function() {
service.getAvailableDates().then(function(data) {
result = data;
// use done() here??
});
});
it('first call to fetch available dates hits sessionService and returns dates from the service', function () {
rootScope.$apply(); // ??
console.log(result); // this is printing undefined
expect(spy).toHaveBeenCalled(); // this passes
expect(window.sessionStorage.getItem).toHaveBeenCalled(); // this passes
});
});
我尝试了各种方法,但不知道如何测试 AvailableDates.getAvailableDates() 调用的结果。当我使用 done() 时,我收到错误: 超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调(我已尝试覆盖此值,但运气不好)。
如果我取出 done(),并在调用 .then 之后调用 rootScope.$apply(),我会得到一个未定义的值作为结果。
我做错了什么?
【问题讨论】:
-
不确定,但也可能将 promise 存储在变量中 (
thePromise),然后在您的测试中调用thePromise.done()而不是rootScope.$apply() -
done() (在我的测试中)指的是 jasmine 的 done() jasmine.github.io/2.2/… 我正在使用 Angular 的承诺库 $q docs.angularjs.org/api/ng/service/$q 它有一个 then() 调用而不是 jquery 的 done()打电话
-
为了进一步混淆,Angular 的 $http 库返回了一种特殊的 promise(它有 .success() 和 .error 回调)。
标签: javascript angularjs unit-testing jasmine angular-promise