У меня есть код, который запускает таймер, когда пользователь активен, а также трансляции и события, чтобы сохранить сеанс.
В контроллере у меня есть код для прослушивания этого события и обновления сеанса.
Я хочу протестировать этого слушателя
$scope.$on('Keepalive', function () {
//every 45 minutes make a call to refresh the session.
var promise = authService.keepAliveSession();
promise.then(function(userPreferenceData) {
dataTransfer.setUserPref(userPreferenceData);
}, function(error) {
console.log("promise error!!"+error);
});
});
мой сервис keepalive возвращает обещание, которое будет разрешено после возврата httpbackend.
factory.keepAliveSession = function () {
var deferred = $q.defer();
req=...some stuff...
$http(req)
.success(
function (data, status) {
if ( data.user ) {
// Received data about the logged in user
deferred.resolve(factory.userPreferenceData);
} else {
// User is not authenticated; redirect to login
$window.location = data.redirect;
}
}
).error(function (error) {
// Error in oAuth refresh service
deferred.reject("Error in session keepalive"+ error);
});
return deferred.promise;
}
вот тест
it('Test for keepalive', function() {
console.log('starting for keepalive...');
httpBackend.when('POST', "http://example.com/refreshSession").respond(getMocks().response.oAuthResponseExternal);
spyOn(authServiceMock, "keepAliveSession").and.callThrough();
spyOn(dataTransferMock, "setUserPref").and.callThrough();
rootScope.$broadcast('Keepalive');
expect(authServiceMock.keepAliveSession).toHaveBeenCalled();
rootScope.$digest;
expect(dataTransferMock.setUserPref).toHaveBeenCalled();
});
Первое утверждение является успешным, но второе (после дайджеста) терпит неудачу.
Как я могу заставить обещание быть разрешенным или отвергнутым? Нужно ли мне как-то издеваться над $ q?
Трудно сказать наверняка, не видя притворных реализаций, как вы подключаете модуль и как вы создаете контроллер.
Я предполагаю, что обещание, которое возвращается из authServiceMock.keepAliveSession
никогда не будет разрешено, что приведет к тому, что функция успеха, которую обеспечивает dataTransfer.setUserPref
никогда не будет выполнена.
Если вы, например, имеете макет, который выглядит так:
var deferred;
var authServiceMock = {
keepAliveSession: function () {
deferred = q.defer();
return deferred.promise;
}
};
Вам необходимо вручную выполнить тест или разрешить или отклонить обещание перед запуском цикла дайджеста, в зависимости от того, в каком случае вы тестируете:
expect(authServiceMock.keepAliveSession).toHaveBeenCalled();
deferred.resolve('something');
$rootScope.$digest();
expect(dataTransferMock.setUserPref).toHaveBeenCalled();
Обратите внимание, что вам нужно выполнить функцию $digest
, в вашем примере у вас есть rootScope.$digest;
,
На другой ноте, мне кажется, вы немного смешаете проблемы тестирования.
С моей точки зрения, это то, что должен проверить ваш контроллер:
Keepalive
уволено - authService.keepAliveSession
следует называтьauthService.keepAliveSession
разрешено - необходимо вызвать dataTransfer.setUserPref
и передать правильные данныеauthService.keepAliveSession
от authService.keepAliveSession
отклонен - сообщение об ошибке должно быть зарегистрировано Детали реализации служб не должны иметь значения (кроме того, что authService.keepAliveSession
возвращает обещание), и в этом случае вам не нужно привлекать httpBackend
.
Настройка поддельных данных возврата с помощью httpBackend
следует использовать при проверке фактической службы, использующей службу $http
.
Ниже приведен альтернативный способ проверить это, используя spyOn
и callFake
вместо использования макетных реализаций.
describe('myApp', function() {
var $rootScope;
var $controller;
var authService;
var dataTransfer;
var $log;
var myController;
beforeEach(function() {
module('myApp');
inject(function(_$rootScope_, _$controller_, _authService_, _dataTransfer_, _$q_, _$log_) {
$rootScope = _$rootScope_;
$controller = _$controller_;
authService = _authService_;
dataTransfer = _dataTransfer_;
$q = _$q_;
$log = _$log_;
});
myController = $controller('MyController', {
$scope: $rootScope.$new()
});
});
it('On event "Keepalive" - should call "authService.keepAliveSession"', function() {
spyOn(authService, 'keepAliveSession').and.callFake(function() {
var deferred = $q.defer();
return deferred.promise;
});
$rootScope.$broadcast('Keepalive');
expect(authService.keepAliveSession).toHaveBeenCalled();
});
it('Promise from "authService.keepAliveSession" is resolved - should call "dataTransfer.setUserPref"', function() {
var data = {};
spyOn(authService, 'keepAliveSession').and.callFake(function() {
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
});
spyOn(dataTransfer, 'setUserPref');
$rootScope.$broadcast('Keepalive');
$rootScope.$digest();
expect(dataTransfer.setUserPref).toHaveBeenCalledWith(data);
});
it('Promise from "authService.keepAliveSession" is rejected - should not call "dataTransfer.setUserPref"', function() {
var data = {};
spyOn(authService, 'keepAliveSession').and.callFake(function() {
var deferred = $q.defer();
deferred.reject(data);
return deferred.promise;
});
spyOn(dataTransfer, 'setUserPref');
$rootScope.$broadcast('Keepalive');
$rootScope.$digest();
expect(dataTransfer.setUserPref).not.toHaveBeenCalled();
});
it('Promise from "authService.keepAliveSession" is rejected - should log message', function() {
var error = {};
spyOn(authService, 'keepAliveSession').and.callFake(function() {
var deferred = $q.defer();
deferred.reject(error);
return deferred.promise;
});
spyOn($log, 'log');
$rootScope.$broadcast('Keepalive');
$rootScope.$digest();
expect($log.log).toHaveBeenCalledWith(error);
});
});