2015-12-21 43 views
1

我想测试它使用controllerAs语法的控制器。我的问题是,当我尝试在控制器上测试一个函数时,我得到“预期未定义被定义。”问题单元测试controllerAs:登录控制器返回一个承诺

控制器(缩短版)

(function (angular) { 
    'use strict'; 

    /* @ngInject */ 
    function PreflightCtrl($state, $window, $timeout, $stateParams, toastr, accountService, servicesService, geoService, visitService, localStorageService, Notifications, service, UTILS) { 

    /* Exported Vars */ 
    var vm = this; 

    /* Exported functions */ 
    vm.verifyDob = verifyDob; 

    function verifyDob() { 
     if (!vm.form.dob || (vm.form.dob.length !== 8 && vm.form.dob.length !== 10)){ 
     return; 
     } 
     if(vm.form.dob.length === 8){ 
     var lastTwoDigits = vm.form.dob.substr(vm.form.dob.length-2); 
     if(lastTwoDigits === '19'){ 
      return; 
     } 
     } 
     var dob = new Date(vm.form.dob); 
     vm.verifyingDob = true; 
     accountService.verifyDOB(dob) 
     .success(function(data){ 
      vm.genderDisabled = false; 
      vm.dobError = false; 
      $timeout(function() { 
      dobInput.blur(); 
      }); 
     }) 
     .error(function (status) { 
      vm.genderDisabled = true; 
      vm.dobError = true; 
     }) 
     .finally(function() { 
      vm.verifyingDob = false; 
     }); 
    } 
    } 

    angular 
    .module('app') 
    .controller('PreflightCtrl', PreflightCtrl); 

}(angular)); 

测试

describe('PreflightCtrl', function(){ 
    var PreflightCtrl, $state, $window, $timeout, $stateParams, toastr, accountService, servicesService, geoService, visitService, localStorageService, Notifications, service, UTILS, mockAccountService, mockServicesService; 

    beforeEach(module('app')); 

    beforeEach(inject(function($controller, _$state_, _$window_, _$timeout_, _$stateParams_, _toastr_, _accountService_, _servicesService_, _geoService_, _visitService_, _localStorageService_, _Notifications_, _UTILS_){ 

    //mock services used in PreflightCtrl 
    mockAccountService = { 
     verifyDOB: function verifyDOB(dob){ 
     return { 
      success: function(callback){ 
      callback(dob); 
      } 
     } 
     }, 
     isPermUser: function isPermUser(){ 
     return { 
      success: function(callback){ 
      callback(true); 
      } 
     } 
     }, 
     profile: { 
     gender: 'male' 
     } 
    }; 

    mockServicesService = { 
     isGenderAllowed: function isGenderAllowed(serviceCode, gender){ 
     return true; 
     } 
    } 

    //prepare for dependency injection 
    $state = _$state_; 
    $window = _$window_; 
    $timeout = _$timeout_; 
    $stateParams = _$stateParams_; 
    toastr = _toastr_; 
    accountService = mockAccountService; 
    servicesService = mockServicesService; 
    geoService = _geoService_; 
    visitService = _visitService_; 
    localStorageService = _localStorageService_; 
    Notifications = _Notifications_; 
    service = {"id": 3, "code": "HL", "flags": {"multi_medicine": false}, "genders": ["male"], "name": "Hair Loss", "product": {"count": 3}, "visible": 1}; 
    UTILS = _UTILS_; 

    //spy on the mocked services 
    spyOn(accountService, 'verifyDOB').and.callThrough(); 
    spyOn(servicesService, 'isGenderAllowed').and.callThrough(); 

    //create the controller 
    PreflightCtrl = $controller('PreflightCtrl', { 
     $state: $state, 
     $window: $window, 
     $timeout: $timeout, 
     $stateParams: $stateParams, 
     toastr: toastr, 
     accountService: accountService, 
     servicesService: servicesService, 
     geoService: geoService, 
     visitService: visitService, 
     localStorageService: localStorageService, 
     Notifications: Notifications, 
     service: service, 
     UTILS: UTILS 
    }); 

    })); 

    it('should have a defined controller', function(){ 
    expect(PreflightCtrl).toBeDefined(); 
    }); 

    it('should have a defined function called verifyDob', function(){ 
    console.log(PreflightCtrl); 
    expect(PreflightCtrl.verifyDob).toBeDefined(); 
    }); 

    it('should verify a DOB', function(){ 

    PreflightCtrl.form.dob = '01/01/1990'; 
    PreflightCtrl.verifyDob(); 
    expect(PreflightCtrl.verifyingDob).toBe(false); 
    }); 
}); 

当我运行测试,这是我得到的输出:

运行“报应:单位“(karma)任务 PhantomJS 1.9.8(Mac OS X 0.0.0)日志:'警告:试图不止一次加载角。' PhantomJS 1.9.8(Mac OS X 0.0.0)PreflightCtrl应该有一个已定义的函数,它被称为“ verifyDob失败 预期未定义以定义。 at /Users/tracy/Projects/LemonaidClinic/src/views/preflight/preflight.controller.spec.js:80 PhantomJS 1.9.8(Mac OS X 0.0.0)PreflightCtrl应验证DOB失败 TypeError:'undefined '不是(评价对象 'PreflightCtrl.form.dob = '01/01/1990'') 在/Users/tracy/Projects/LemonaidClinic/src/views/preflight/preflight.controller.spec.js:85 PhantomJS 1.9.8(Mac OS X 0.0.0):执行15(15失败)(0.006秒/ 0.204秒) 警告:任务“因果:单位”失败。使用--force继续。

由于警告中止。

80行是此行:预期(PreflightCtrl.verifyDob).toBeDefined();

和线85是这样的:PreflightCtrl.form.dob = '01/01/1990' ;

,你可以看到,第一行是控制器,它返回一个承诺,这意味着任何函数或变量是需要在那里控制器上的日志。

我也不清楚为什么角试图加载不止一次,但它似乎并没有被影响任何其他测试。

我在做什么错?

预先感谢您。

+0

我认为控制器直到调用$ rootScope。$ apply()之后才存在。另外,您不需要手动注入每个依赖项。如果您不在测试中定制/覆盖它们,Angular将注入它们。 –

+0

我在哪里添加$ rootScope。$ apply()?我手动创建的唯一依赖项是在运行测试时导致错误的依赖项,并且创建这些模拟依赖项修复了这些错误,所以我认为它们是必需的。 –

回答

0

我会做更是这样的:

 
var scope = $rootScope.$new(); 

$controller('myController as vm', {$scope:scope, /*your dependency tree hell*/}); 
$rootScope.$apply(); 

vm = scope.vm;//This is your new controller, you can refer to it in tests. 

我认为你有嘲笑的事实这么多说,你的控制器有太多的依赖,直接和/或间接的影响。

但是,如果您无法解决这个问题,只需创建一个名为“mocks”的文件夹并放入与真实ID相同的文件并将Karma指向夹。那些将覆盖实际的依赖关系。缺点是,你还是得做,如果你需要比你的注册模拟不同的东西一次性的嘲笑,但它去除了设立嘲笑在每个测试的任务。