我有一些代码在用户处于活动状态时运行计时器,并通过广播和事件来保持会话处于活动状态。
在控制器中,我有一些代码来监听该事件并刷新会话。
我想测试这个监听器
$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服务返回一个promise,它将在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?
答案 0 :(得分:1)
如果没有看到模拟实现,如何连接模块以及如何创建控制器,很难肯定地说。
我的猜测是从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
返回一个承诺),在这种情况下你不需要涉及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);
});
});