【问题标题】:Karma/Jasmine Testing Angular with Controller ModuleKarma/Jasmine 使用控制器模块测试 Angular
【发布时间】:2017-02-24 11:29:44
【问题描述】:

我正在尝试测试我的应用程序,该应用程序在其自己的模块上定义了每个控制器,即不是作为应用程序模块的控制器,然后作为主应用程序模块的依赖项加载。当我尝试使用 Karma/Jasmine 运行仅检查 loginController 是否已定义的测试时,我得到以下输出:

'预期未定义的定义。'

编辑

我更新了 login.controller.spec 并将 karma 浏览器切换到 chrome,这给了我更多有用的调试信息。现在我收到一个与添加到主应用程序文件中的 $httpProvider.interceptors 的工厂相关的错误:

未知提供者:authFactoryProvider

我发现与此相关的类似问题已通过包含 angular-translate-loader-static-files.js 得到解决,该文件在 karma 运行时被加载:

调试 [web-server]:服务(缓存):/path/to/my/app/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js

如何解决所有这些与 karma 相关的依赖问题?

index.js

'use strict';

angular.module('app',
    [
    //'mockBackend', //uncomment when loading mock backend
    'ngAnimate',
    'ngCookies',
    'ngTouch',
    'ngSanitize',
    'ngResource',
    'ui.bootstrap',
    'ui.router',
    'ui.router.stateHelper',
    'pascalprecht.translate',
    'utilsModule',
    'loginModule',
    'vsmsPackageModule',
    'vsmsCampaignModule',
    'vdmsCampaignModule',
    'vdmsDashboardModule',
    'daterangepicker',
    'ui.event',
    'idmAdminModule',
    'helpdeskModule',
    'ncy-angular-breadcrumb',
    'rzModule',
    'vsmsDashboardModule',
    'highcharts-ng',
    'permission',
    'dndLists'
    ])
  .config(function ($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider, $translateProvider, $breadcrumbProvider, $compileProvider) {
    $urlRouterProvider.otherwise('/');
    //initialize get if not there
    if (!$httpProvider.defaults.headers.get) {
      $httpProvider.defaults.headers.get = {};
    }
    //disable IE ajax request caching
    $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
    // extra
    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';

    $locationProvider.html5Mode({
      enabled: false,
      requireBase: false
    });
    $translateProvider.useSanitizeValueStrategy('sanitize');
    $translateProvider.useStaticFilesLoader({
      prefix: '/locales/',
      suffix: '.json'
    });

    $translateProvider
    .preferredLanguage('en_us')
    .fallbackLanguage('en_us');

    $breadcrumbProvider.setOptions({
      templateUrl: 'components/templates/breadcrumb.tpl.html'
    });
    $compileProvider.debugInfoEnabled(false);
    // $compileProvider.aHrefSanitizationWhitelist(/^\s*(|blob|):/);
    $httpProvider.interceptors.push('authFactory');
        $httpProvider.interceptors.push('headersFactory');
   })

login.module.js

angular.module('loginModule', []);

login.controller.js

  angular.module('loginModule')
  .controller('loginController', login);

  login.$inject = [
      '$log',
      '$uibModal',
      '$rootScope',
      'storageFactory',
      'loginFactory',
      '$state',
      'RoleStore',
      'PermissionStore'
  ];

  function login($log, $uibModal, $rootScope, storageFactory, loginFactory, $state, RoleStore, PermissionStore) {

      /* jshint validthis: true */
      var vm = this;
      vm.loginUser = loginUser;
      vm.forgotPassword = forgotPassword;
      vm.errorCode = null;
      PermissionStore.clearStore();

      function loginUser() {
      ...

我只是想测试控制器是否存在并且我无法克服错误:

预期未定义。

login.controller.spec.js

describe('loginController', function() {

  beforeEach(module('app'));

  var $controller,
  $scope,
  $log,
  $uibModal,
  $rootScope,
  storageFactory,
  loginFactory,
  $state,
  RoleStore,
  PermissionStore,
  vsmsCoreFactory;

  beforeEach(inject(function(_$controller_, _$log_, _$uibModal_, _$rootScope_, _storageFactory_, _loginFactory_, _$state_, _RoleStore_, _PermissionStore_, _vsmsCoreFactory_){
    $controller = _$controller_;
    $scope = $rootScope.new();
    $log = _$log_;
    $uibModal = _$uibModal_;
    $rootScope = _$rootScope_;
    storageFactory = _storageFactory_;
    loginFactory = _loginFactory_;
    $state = _$state_;
    RoleStore = _RoleStore_;
    PermissionStore = _PermissionStore_;
    vsmsCoreFactory = _vsmsCoreFactory_;
  }));

  describe('vm.loginUser', function() {
    it('should be defined', function() {
      var loginController = $controller('loginController', {
        $log: $log,
        $uibModal: $uibModal,
        $rootScope: $rootScope,
        storageFactory: storageFactory,
        loginFactory: loginFactory,
        $state: $state,
        RoleStore: RoleStore,
        PermissionStore: PermissionStore,
        vsmsCoreFactory: vsmsCoreFactory
      });
      expect(loginController).toBeDefined();
      // expect(testController.model.name).toEqual("controllerAs vm test");
    });
  });

});

unit-tests.js

'use strict';

var gulp = require('gulp');

var $ = require('gulp-load-plugins')();

var wiredep = require('wiredep');

var paths = gulp.paths;

function runTests (singleRun, done) {
  var bowerDeps = wiredep({
    directory: 'bower_components',
    exclude: ['bootstrap-sass-official'],
    dependencies: true,
    devDependencies: true
  });

  var testFiles = bowerDeps.js.concat([
    './src/app/index.js',
    './src/components/scripts/ui-bootstrap-custom-tpls-2.1.3.js',
    './src/{app,components}/**/*.module.js',
    './src/{app,components}/**/*.factory.js',
    './src/{app,components}/**/*.controller.js',
    './src/{app,components}/**/*.spec.js'
  ]);

  gulp.src(testFiles)
    .pipe($.karma({
      configFile: 'karma.conf.js',
      action: (singleRun)? 'run': 'watch'
    }))
    .on('error', function (err) {
      // Make sure failed tests cause gulp to exit non-zero
      throw err;
    });
}

gulp.task('test', function (done) { runTests(true /* singleRun */, done) });
gulp.task('test:auto', function (done) { runTests(false /* singleRun */, done) });

【问题讨论】:

    标签: javascript angularjs jasmine karma-jasmine


    【解决方案1】:

    问题在于您的 login.module.js 文件。

    在定义loginModule 时,您必须注入ui.bootstrapui.router 作为依赖项。否则在定义loginController时将无法获取$uibModal$state

    这应该是你loginModule的定义

    angular.module('loginModule', ['ui.bootstrap', 'ui.router']);
    

    PS:我在这里假设storageFactoryloginFactoryRoleStorePermissionStore 是在loginModule 本身上定义的。

    希望这会有所帮助!

    【讨论】:

    • 这些依赖被注入到 index.js 文件中。我尝试将它们添加到 login.module.js 文件中,但仍然出现相同的错误。
    【解决方案2】:

    请参考下面已经回答的链接。

    How to inject controller dependencies in Jasmine tests?

    loginController 依赖项未在您的单元测试中通过。

    $controller 的第二个参数是控制器依赖。

    传递了空依赖。

    $controller('loginController', {});

    确保在测试 loginColtroller 之前加载了所有依赖模块。

    我修改了你的代码。我希望它会起作用。

    'use strict';
    
    describe('loginController', function() {
    
      beforeEach(module('loginModule'));
    
      var loginController;
    
      beforeEach(inject(function($controller, _$log_, _$uibModal_, _$rootScope_, _storageFactory_, _loginFactory_, _$state_, _RoleStore_, _PermissionStore_ ){
        scope = _$rootScope_.$new();
        loginController = $controller('loginController', 
        {   // all dependencies has to be passed in order
            '$log' : _$log_,
            '$uibModal' : _$uibModal_,
            '$rootScope' : _$rootScope_,
            'storageFactory' : _storageFactory_,
            'loginFactory': _loginFactory_,
            '$state': _$state_,
            'RoleStore': _RoleStore_,
            'PermissionStore': _PermissionStore_
        }, 
        {});
      }));
    
      it('should be defined', function() {
        expect(loginController).toBeDefined();
      });
    
    });
    

    【讨论】:

    • 谢谢,但这并没有解决问题。现在我只看到测试失败但没有解释原因。
    • 你能创建一个 plunker 吗?
    • 尝试 beforeEach(module('app'));而不是 beforeEach(module('loginModule'));
    猜你喜欢
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多