如何为承诺写一个业力测试

时间:2016-06-03 18:48:38

标签: angularjs karma-jasmine

我有一些代码在用户处于活动状态时运行计时器,并通过广播和事件来保持会话处于活动状态。

在控制器中,我有一些代码来监听该事件并刷新会话。

我想测试这个监听器

$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?

1 个答案:

答案 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;

另一方面,在我看来,你正在混合测试问题。

从我的角度来看,这是你的控制器应该测试的:

  1. 触发Keepalive事件时,应调用authService.keepAliveSession
  2. 如果authService.keepAliveSession的承诺得到解决,则应调用dataTransfer.setUserPref并传递正确的数据
  3. 如果拒绝来自authService.keepAliveSession的承诺,则应记录错误消息
  4. 服务的实现细节无关紧要(除了authService.keepAliveSession返回一个承诺),在这种情况下你不需要涉及httpBackend

    在测试使用httpBackend服务的实际服务时,应使用$http设置虚假返回数据。

    下面是另一种测试方法,使用spyOncallFake代替使用模拟实现。

    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);
      });
    });
    

    演示: http://plnkr.co/edit/L1uks0skH2N5bAXGoe90?p=preview

相关问题