Karma-Jasmine框架下Angular控制器测试用例无法加载问题
我最近碰到个头疼的问题:给Angular项目里的loginController写简单测试用例,运行后既没有错误提示,也加载不了任何测试用例,执行结果始终显示Executed 0 of 0 ERROR (0.005 secs / 0 secs)。相关代码如下:
app.js
var myApp = angular.module('myApp',[ 'ui.bootstrap', 'dialogs', 'ui.router','base64','ngtimeago', 'cfp.loadingBar', 'ngStorage', 'ngCookies', 'ngTable','ngRoute', 'angularUtils.directives.dirPagination', 'ngSanitize','ngTagsInput', 'ngIdle','angular.filter','angular-encryption','ngImgCrop']);
loginController.js
myApp.controller("loginController",['$scope','$rootScope','$state','APIServices','$http','$localStorage','cfpLoadingBar','$log','sha256','MFEEDBACK_CONSTANT_MESSAGES', function($scope, $rootScope, $state, APIServices, $http,$localStorage,cfpLoadingBar,$log,sha256) { var lc = this; lc.test = "hello"; }
loginController.specs.js
describe('Controllers', function(){ beforeEach(module('myApp')); describe('loginController', function(){ var loginController; beforeEach(inject(function($controller,$rootScope){ var state,mockStorage,APIService,mockHTTP,mockLoadingBar,log,sha256,messages; var mockScope,mockRootScope = $rootScope.$new(); loginController = $controller('loginController',{ $scope:mockScope, $rootScope:mockRootScope, $state:state, APIServices:APIService, $http:mockHTTP, $localStorage:mockStorage, cfpLoadingBar:mockLoadingBar, $log:log, sha256:sha256, MFEEDBACK_CONSTANT_MESSAGES:messages }); })); it('testCase1val should be working', function(){ expect(loginController.test).toBe('hello'); }); }); });
问题排查与解决步骤
这种“执行0个用例”的情况,一般要么是测试 runner 找不到你的测试文件,要么是代码里的隐性错误导致测试初始化失败但没抛出错误,下面是几个关键检查点:
1. 检查测试框架(比如Karma)的配置
首先确认你的Karma配置文件(karma.conf.js)里的files数组是否正确包含了所有必要文件,而且顺序不能错:
- 先加载Angular核心库
- 然后是Angular-mocks(用于测试的模拟库)
- 接着是你的应用代码(app.js、loginController.js)
- 最后才是测试用例文件
示例配置:
files: [ 'node_modules/angular/angular.js', 'node_modules/angular-mocks/angular-mocks.js', 'app.js', 'loginController.js', 'loginController.specs.js' ]
另外要注意测试文件的路径是否正确,如果你的spec文件放在test/目录下,路径要写成test/loginController.specs.js。
2. 修复控制器的依赖注入错误
看你的loginController代码,依赖数组最后声明了MFEEDBACK_CONSTANT_MESSAGES,但对应的函数参数里却没有这个参数,这会导致Angular的依赖注入不匹配,虽然可能不会直接抛出明显错误,但会导致控制器初始化失败,进而影响测试用例加载。修改后的控制器代码:
myApp.controller("loginController",['$scope','$rootScope','$state','APIServices','$http','$localStorage','cfpLoadingBar','$log','sha256','MFEEDBACK_CONSTANT_MESSAGES', function($scope, $rootScope, $state, APIServices, $http,$localStorage,cfpLoadingBar,$log,sha256, MFEEDBACK_CONSTANT_MESSAGES) { var lc = this; lc.test = "hello"; }]); // 注意这里还要闭合控制器的括号,你原来的代码漏掉了
3. 初始化测试用例里的模拟依赖
你的测试用例里,state、mockStorage这些依赖都是只声明没赋值的变量,虽然Angular允许传入undefined,但最好简单初始化一下,避免潜在的初始化问题:
describe('Controllers', function(){ beforeEach(module('myApp')); describe('loginController', function(){ var loginController; beforeEach(inject(function($controller,$rootScope){ // 简单初始化模拟依赖,不需要真实实现,只要存在即可 var state = {}; var mockStorage = {}; var APIService = {}; var mockHTTP = {}; var mockLoadingBar = {}; var log = {}; var sha256 = {}; var messages = {}; var mockScope = $rootScope.$new(); var mockRootScope = $rootScope.$new(); loginController = $controller('loginController',{ $scope:mockScope, $rootScope:mockRootScope, $state:state, APIServices:APIService, $http:mockHTTP, $localStorage:mockStorage, cfpLoadingBar:mockLoadingBar, $log:log, sha256:sha256, MFEEDBACK_CONSTANT_MESSAGES:messages }); })); it('testCase1val should be working', function(){ expect(loginController.test).toBe('hello'); }); }); });
4. 确认测试命令正确
如果你运行测试时指定了非默认的配置文件,要确保命令正确,比如:
karma start my-karma-config.conf.js
如果是用npm scripts运行,检查package.json里的测试命令是否指向正确的配置。
内容的提问来源于stack exchange,提问作者Rushikesh Salunke

