Karma/Jasmine用控制器模块测试Angular

Karma/Jasmine Testing Angular with Controller Module

本文关键字:模块测试 Angular 控制器 Jasmine Karma      更新时间:2023-09-26

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

'预期未定义已定义。'

编辑

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

未知提供商:authFactoryProvider <- authFactory <- $http <- $translateStaticFilesLoader <- $translate

我发现了与此相关的类似问题,通过包含angular-translate-loader-static-files.js来解决,它在karma运行时正在加载:

DEBUG [web-server]: serving (cached):/path/to/my/app/bower_components/angular- translat-load-static-files/angular- translat-load-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) });

请参考下面的链接,它已经被回答了

如何在Jasmine测试中注入控制器依赖?

loginController依赖项在单元测试中没有通过。

$controller的第二个参数表示控制器依赖项。

传递空依赖项。

美元控制器(loginController, {});

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

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

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

问题是你的login.module.js文件。

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

这应该是你的loginModule的定义

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

PS:我在这里假设storageFactory, loginFactory, RoleStorePermissionStore是在loginModule本身上定义的。

希望这对你有帮助!