Angular Karma/Jasmine 单元测试不工作
Angular Karma/Jasmine Unit Test not working
我正在尝试为我的新 Angular 应用程序编写单元测试,但遇到了麻烦。下面是我的控制器。
'use strict';
angular.module('nileLeApp')
.controller('RegisterController', function ($scope, $translate, $timeout, vcRecaptchaService, Auth, Country, Timezone, RecaptchaService) {
$scope.success = null;
$scope.error = null;
$scope.doNotMatch = null;
$scope.errorUserExists = null;
$scope.registerAccount = {};
$timeout(function () {
angular.element('[ng-model="registerAccount.email"]').focus();
});
$scope.loadCountries = function () {
Country.getCountries()
.then(function (result) {
$scope.countries = result.data;
});
};
$scope.loadTimezones = function () {
Timezone.getTimezones()
.then(function (result) {
$scope.timezones = result.data;
});
};
// ============ Recaptcha specific code START ===============
$scope.recaptcha = {};
$scope.recaptcha.recaptchaResponse = null;
$scope.recaptchaWidgetId = null;
$scope.setResponse = function (response) {
$scope.recaptcha.recaptchaResponse = response;
$scope.recaptchaMissing = false;
};
$scope.setWidgetId = function (widgetId) {
$scope.recaptchaWidgetId = widgetId;
};
$scope.cbExpiration = function () {
$scope.recaptcha.recaptchaResponse = null;
};
// ============ Recaptcha specific code END ===============
$scope.createAccount = function () {
Auth.createAccount($scope.registerAccount).then(function (response) {
$scope.success = true;
}).catch(function (response) {
$scope.success = false;
});
}
$scope.register = function () {
$scope.recaptchaMissing = false;
$scope.recaptchaInvalid = false;
if ($scope.recaptcha.recaptchaResponse != null) {
RecaptchaService.verify($scope.recaptcha).$promise
.then(function (response) {
if (response.data) {
$scope.createAccount();
} else {
$scope.recaptchaInvalid = true;
vcRecaptchaService.reload($scope.recaptchaWidgetId); // Reload captcha
}
}).catch(function (response) {
});
} else {
$scope.recaptchaMissing = true;
}
};
$scope.loadCountries();
$scope.loadTimezones();
});
下面是我正在尝试的测试。
'use strict';
describe('Register Controllers Tests', function () {
describe('RegisterController', function () {
// actual implementations
var $scope;
var $q;
// mocks
var MockTimeout;
var MockTranslate;
var MockAuth;
var MockCountry;
var MockTimezone;
// local utility function
var createController;
beforeEach(inject(function ($injector) {
$q = $injector.get('$q');
$scope = $injector.get('$rootScope').$new();
MockTimeout = jasmine.createSpy('MockTimeout');
MockAuth = jasmine.createSpyObj('MockAuth', ['createAccount']);
MockCountry = jasmine.createSpyObj('MockCountry', ['getCountries']);
MockTimezone = jasmine.createSpyObj('MockTimezone', ['getTimezones']);
MockTranslate = jasmine.createSpyObj('MockTranslate', ['use']);
var locals = {
'$scope': $scope,
'$translate': MockTranslate,
'$timeout': MockTimeout,
'Auth': MockAuth,
'Country': MockCountry,
'Timezone': MockTimezone
};
createController = function () {
$injector.get('$controller')('RegisterController', locals);
};
}));
it('should load countries on page load', function () {
var mockCountryResponse = [{
'countryId': 1,
'alpha2Code': "AF",
'countryName': "Afghanistan"
}];
MockCountry.getCountries.and.returnValue($q.resolve(mockCountryResponse));
MockTimezone.getTimezones.and.returnValue($q.resolve());
MockAuth.createAccount.and.returnValue($q.resolve());
// given
createController();
$scope.$apply($scope.loadCountries);
expect($scope.countries).toEqual(mockCountryResponse);
});
});
上述期望不成立,因为 $scope.countries 未定义。以下是错误信息。
TypeError: 'undefined' is not an object (evaluating 'result.data')
此外,我看到测试由于某种奇怪的原因被调用了两次。下面是我的 Karma 配置文件。
// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html
module.exports = function (config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '../../',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// bower:js
'main/webapp/bower_components/es5-shim/es5-shim.js',
'main/webapp/bower_components/jquery/dist/jquery.js',
'main/webapp/bower_components/angular/angular.js',
'main/webapp/bower_components/angular-animate/angular-animate.js',
'main/webapp/bower_components/angular-aria/angular-aria.js',
'main/webapp/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'main/webapp/bower_components/bootstrap/dist/js/bootstrap.js',
'main/webapp/bower_components/angular-bootstrap-nav-tree/dist/abn_tree_directive.js',
'main/webapp/bower_components/angular-file-upload/angular-file-upload.js',
'main/webapp/bower_components/angular-messages/angular-messages.js',
'main/webapp/bower_components/skycons/skycons.js',
'main/webapp/bower_components/angular-skycons/angular-skycons.js',
'main/webapp/bower_components/angular-smart-table/dist/smart-table.min.js',
'main/webapp/bower_components/angular-touch/angular-touch.js',
'main/webapp/bower_components/angular-cache-buster/angular-cache-buster.js',
'main/webapp/bower_components/angular-cookies/angular-cookies.js',
'main/webapp/bower_components/angular-dynamic-locale/src/tmhDynamicLocale.js',
'main/webapp/bower_components/angular-local-storage/dist/angular-local-storage.js',
'main/webapp/bower_components/angular-loading-bar/build/loading-bar.js',
'main/webapp/bower_components/angular-resource/angular-resource.js',
'main/webapp/bower_components/angular-sanitize/angular-sanitize.js',
'main/webapp/bower_components/angular-translate/angular-translate.js',
'main/webapp/bower_components/messageformat/messageformat.js',
'main/webapp/bower_components/angular-translate-interpolation-messageformat/angular-translate-interpolation-messageformat.js',
'main/webapp/bower_components/angular-translate-loader-partial/angular-translate-loader-partial.js',
'main/webapp/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
'main/webapp/bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.js',
'main/webapp/bower_components/angular-translate-storage-local/angular-translate-storage-local.js',
'main/webapp/bower_components/angular-ui-router/release/angular-ui-router.js',
'main/webapp/bower_components/moment/moment.js',
'main/webapp/bower_components/fullcalendar/dist/fullcalendar.js',
'main/webapp/bower_components/angular-ui-calendar/src/calendar.js',
'main/webapp/bower_components/angular-ui-grid/ui-grid.js',
'main/webapp/bower_components/angular-ui-select/dist/select.js',
'main/webapp/bower_components/angular-ui-utils/ui-utils.js',
'main/webapp/bower_components/angular-xeditable/dist/js/xeditable.js',
'main/webapp/bower_components/angularjs-toaster/toaster.js',
'main/webapp/bower_components/angular-strap/dist/angular-strap.js',
'main/webapp/bower_components/angular-strap/dist/angular-strap.tpl.js',
'main/webapp/bower_components/angular-recaptcha/release/angular-recaptcha.js',
'main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js',
'main/webapp/bower_components/bootstrap-filestyle/src/bootstrap-filestyle.js',
'main/webapp/bower_components/bootstrap-slider/bootstrap-slider.js',
'main/webapp/bower_components/bootstrap-tagsinput/dist/bootstrap-tagsinput.js',
'main/webapp/bower_components/bootstrap-wysiwyg/bootstrap-wysiwyg.js',
'main/webapp/bower_components/bower-jvectormap/jquery-jvectormap-1.2.2.min.js',
'main/webapp/bower_components/datatables/media/js/jquery.dataTables.js',
'main/webapp/bower_components/flot/jquery.flot.js',
'main/webapp/bower_components/flot-spline/js/jquery.flot.spline.js',
'main/webapp/bower_components/flot.tooltip/js/jquery.flot.tooltip.js',
'main/webapp/bower_components/footable/js/footable.js',
'main/webapp/bower_components/html5sortable/jquery.sortable.js',
'main/webapp/bower_components/json3/lib/json3.js',
'main/webapp/bower_components/ng-grid/build/ng-grid.js',
'main/webapp/bower_components/intl-tel-input/build/js/intlTelInput.min.js',
'main/webapp/bower_components/intl-tel-input/lib/libphonenumber/build/utils.js',
'main/webapp/bower_components/ng-intl-tel-input/dist/ng-intl-tel-input.js',
'main/webapp/bower_components/ngImgCrop/compile/minified/ng-img-crop.js',
'main/webapp/bower_components/ngstorage/ngStorage.js',
'main/webapp/bower_components/ng-file-upload/ng-file-upload.js',
'main/webapp/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js',
'main/webapp/bower_components/oclazyload/dist/ocLazyLoad.min.js',
'main/webapp/bower_components/screenfull/dist/screenfull.js',
'main/webapp/bower_components/slimscroll/jquery.slimscroll.min.js',
'main/webapp/bower_components/textAngular/dist/textAngular.min.js',
'main/webapp/bower_components/venturocket-angular-slider/build/angular-slider.js',
'main/webapp/bower_components/videogular/videogular.js',
'main/webapp/bower_components/videogular-buffering/buffering.js',
'main/webapp/bower_components/videogular-controls/controls.js',
'main/webapp/bower_components/videogular-ima-ads/ima-ads.js',
'main/webapp/bower_components/videogular-overlay-play/overlay-play.js',
'main/webapp/bower_components/videogular-poster/poster.js',
'main/webapp/bower_components/waves/dist/waves.min.js',
'main/webapp/bower_components/angular-mocks/angular-mocks.js',
// endbower
'main/webapp/scripts/app/app.js',
'main/webapp/scripts/app/**/*.+(js|html)',
'main/webapp/scripts/components/**/*.+(js|html)',
'test/javascript/spec/helpers/module.js',
'test/javascript/spec/helpers/httpBackend.js',
'test/javascript/**/!(karma.conf|protractor.conf).js'
],
// list of files / patterns to exclude
exclude: ['test/javascript/e2e/**'],
preprocessors: {
'./main/webapp/scripts/**/*.js': ['coverage'],
'**/*.html': ['ng-html2js']
},
reporters: ['dots', 'jenkins', 'coverage', 'progress'],
jenkinsReporter: {
outputFile: '../build/test-results/karma/TESTS-results.xml'
},
coverageReporter: {
dir: '../build/test-results/coverage',
reporters: [
{type: 'lcov', subdir: 'report-lcov'}
]
},
// web server port
port: 9876,
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true,
// to avoid DISCONNECTED messages when connecting to slow virtual machines
browserDisconnectTimeout : 10000, // default 2000
browserDisconnectTolerance : 1, // default 0
browserNoActivityTimeout : 4*60*1000 //default 10000
});
};
最近几天我一直在写单元测试,因为我发现它们很混乱而且不像 Java 中那样简单。将不胜感激。
The above expectation doesn't work because $scope.countries is undefined
^^ 这不是真的。不是 $scope.countries 未定义,而是 result
未定义,也不是您要分配给 $scope.countries
的 result
,而是与 $scope.timezones
我认为这是你的问题:
MockTimezone.getTimezones.and.returnValue($q.resolve());
您将 undefined 隐式传递给 resolve()
函数,这会在您实例化控制器时引发错误。
它会抛出该错误,因为您在控制器的末尾有这一行:
$scope.loadTimezones();
正是出于这个原因,我停止了在它们内部初始化控制器。现在我使用从 HTML 启动的 ng-init 来完成它。如果你和我一样修改,以后就不会再遇到这样的问题了。
我正在尝试为我的新 Angular 应用程序编写单元测试,但遇到了麻烦。下面是我的控制器。
'use strict';
angular.module('nileLeApp')
.controller('RegisterController', function ($scope, $translate, $timeout, vcRecaptchaService, Auth, Country, Timezone, RecaptchaService) {
$scope.success = null;
$scope.error = null;
$scope.doNotMatch = null;
$scope.errorUserExists = null;
$scope.registerAccount = {};
$timeout(function () {
angular.element('[ng-model="registerAccount.email"]').focus();
});
$scope.loadCountries = function () {
Country.getCountries()
.then(function (result) {
$scope.countries = result.data;
});
};
$scope.loadTimezones = function () {
Timezone.getTimezones()
.then(function (result) {
$scope.timezones = result.data;
});
};
// ============ Recaptcha specific code START ===============
$scope.recaptcha = {};
$scope.recaptcha.recaptchaResponse = null;
$scope.recaptchaWidgetId = null;
$scope.setResponse = function (response) {
$scope.recaptcha.recaptchaResponse = response;
$scope.recaptchaMissing = false;
};
$scope.setWidgetId = function (widgetId) {
$scope.recaptchaWidgetId = widgetId;
};
$scope.cbExpiration = function () {
$scope.recaptcha.recaptchaResponse = null;
};
// ============ Recaptcha specific code END ===============
$scope.createAccount = function () {
Auth.createAccount($scope.registerAccount).then(function (response) {
$scope.success = true;
}).catch(function (response) {
$scope.success = false;
});
}
$scope.register = function () {
$scope.recaptchaMissing = false;
$scope.recaptchaInvalid = false;
if ($scope.recaptcha.recaptchaResponse != null) {
RecaptchaService.verify($scope.recaptcha).$promise
.then(function (response) {
if (response.data) {
$scope.createAccount();
} else {
$scope.recaptchaInvalid = true;
vcRecaptchaService.reload($scope.recaptchaWidgetId); // Reload captcha
}
}).catch(function (response) {
});
} else {
$scope.recaptchaMissing = true;
}
};
$scope.loadCountries();
$scope.loadTimezones();
});
下面是我正在尝试的测试。
'use strict';
describe('Register Controllers Tests', function () {
describe('RegisterController', function () {
// actual implementations
var $scope;
var $q;
// mocks
var MockTimeout;
var MockTranslate;
var MockAuth;
var MockCountry;
var MockTimezone;
// local utility function
var createController;
beforeEach(inject(function ($injector) {
$q = $injector.get('$q');
$scope = $injector.get('$rootScope').$new();
MockTimeout = jasmine.createSpy('MockTimeout');
MockAuth = jasmine.createSpyObj('MockAuth', ['createAccount']);
MockCountry = jasmine.createSpyObj('MockCountry', ['getCountries']);
MockTimezone = jasmine.createSpyObj('MockTimezone', ['getTimezones']);
MockTranslate = jasmine.createSpyObj('MockTranslate', ['use']);
var locals = {
'$scope': $scope,
'$translate': MockTranslate,
'$timeout': MockTimeout,
'Auth': MockAuth,
'Country': MockCountry,
'Timezone': MockTimezone
};
createController = function () {
$injector.get('$controller')('RegisterController', locals);
};
}));
it('should load countries on page load', function () {
var mockCountryResponse = [{
'countryId': 1,
'alpha2Code': "AF",
'countryName': "Afghanistan"
}];
MockCountry.getCountries.and.returnValue($q.resolve(mockCountryResponse));
MockTimezone.getTimezones.and.returnValue($q.resolve());
MockAuth.createAccount.and.returnValue($q.resolve());
// given
createController();
$scope.$apply($scope.loadCountries);
expect($scope.countries).toEqual(mockCountryResponse);
});
});
上述期望不成立,因为 $scope.countries 未定义。以下是错误信息。
TypeError: 'undefined' is not an object (evaluating 'result.data')
此外,我看到测试由于某种奇怪的原因被调用了两次。下面是我的 Karma 配置文件。
// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html
module.exports = function (config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '../../',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// bower:js
'main/webapp/bower_components/es5-shim/es5-shim.js',
'main/webapp/bower_components/jquery/dist/jquery.js',
'main/webapp/bower_components/angular/angular.js',
'main/webapp/bower_components/angular-animate/angular-animate.js',
'main/webapp/bower_components/angular-aria/angular-aria.js',
'main/webapp/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'main/webapp/bower_components/bootstrap/dist/js/bootstrap.js',
'main/webapp/bower_components/angular-bootstrap-nav-tree/dist/abn_tree_directive.js',
'main/webapp/bower_components/angular-file-upload/angular-file-upload.js',
'main/webapp/bower_components/angular-messages/angular-messages.js',
'main/webapp/bower_components/skycons/skycons.js',
'main/webapp/bower_components/angular-skycons/angular-skycons.js',
'main/webapp/bower_components/angular-smart-table/dist/smart-table.min.js',
'main/webapp/bower_components/angular-touch/angular-touch.js',
'main/webapp/bower_components/angular-cache-buster/angular-cache-buster.js',
'main/webapp/bower_components/angular-cookies/angular-cookies.js',
'main/webapp/bower_components/angular-dynamic-locale/src/tmhDynamicLocale.js',
'main/webapp/bower_components/angular-local-storage/dist/angular-local-storage.js',
'main/webapp/bower_components/angular-loading-bar/build/loading-bar.js',
'main/webapp/bower_components/angular-resource/angular-resource.js',
'main/webapp/bower_components/angular-sanitize/angular-sanitize.js',
'main/webapp/bower_components/angular-translate/angular-translate.js',
'main/webapp/bower_components/messageformat/messageformat.js',
'main/webapp/bower_components/angular-translate-interpolation-messageformat/angular-translate-interpolation-messageformat.js',
'main/webapp/bower_components/angular-translate-loader-partial/angular-translate-loader-partial.js',
'main/webapp/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
'main/webapp/bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.js',
'main/webapp/bower_components/angular-translate-storage-local/angular-translate-storage-local.js',
'main/webapp/bower_components/angular-ui-router/release/angular-ui-router.js',
'main/webapp/bower_components/moment/moment.js',
'main/webapp/bower_components/fullcalendar/dist/fullcalendar.js',
'main/webapp/bower_components/angular-ui-calendar/src/calendar.js',
'main/webapp/bower_components/angular-ui-grid/ui-grid.js',
'main/webapp/bower_components/angular-ui-select/dist/select.js',
'main/webapp/bower_components/angular-ui-utils/ui-utils.js',
'main/webapp/bower_components/angular-xeditable/dist/js/xeditable.js',
'main/webapp/bower_components/angularjs-toaster/toaster.js',
'main/webapp/bower_components/angular-strap/dist/angular-strap.js',
'main/webapp/bower_components/angular-strap/dist/angular-strap.tpl.js',
'main/webapp/bower_components/angular-recaptcha/release/angular-recaptcha.js',
'main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js',
'main/webapp/bower_components/bootstrap-filestyle/src/bootstrap-filestyle.js',
'main/webapp/bower_components/bootstrap-slider/bootstrap-slider.js',
'main/webapp/bower_components/bootstrap-tagsinput/dist/bootstrap-tagsinput.js',
'main/webapp/bower_components/bootstrap-wysiwyg/bootstrap-wysiwyg.js',
'main/webapp/bower_components/bower-jvectormap/jquery-jvectormap-1.2.2.min.js',
'main/webapp/bower_components/datatables/media/js/jquery.dataTables.js',
'main/webapp/bower_components/flot/jquery.flot.js',
'main/webapp/bower_components/flot-spline/js/jquery.flot.spline.js',
'main/webapp/bower_components/flot.tooltip/js/jquery.flot.tooltip.js',
'main/webapp/bower_components/footable/js/footable.js',
'main/webapp/bower_components/html5sortable/jquery.sortable.js',
'main/webapp/bower_components/json3/lib/json3.js',
'main/webapp/bower_components/ng-grid/build/ng-grid.js',
'main/webapp/bower_components/intl-tel-input/build/js/intlTelInput.min.js',
'main/webapp/bower_components/intl-tel-input/lib/libphonenumber/build/utils.js',
'main/webapp/bower_components/ng-intl-tel-input/dist/ng-intl-tel-input.js',
'main/webapp/bower_components/ngImgCrop/compile/minified/ng-img-crop.js',
'main/webapp/bower_components/ngstorage/ngStorage.js',
'main/webapp/bower_components/ng-file-upload/ng-file-upload.js',
'main/webapp/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js',
'main/webapp/bower_components/oclazyload/dist/ocLazyLoad.min.js',
'main/webapp/bower_components/screenfull/dist/screenfull.js',
'main/webapp/bower_components/slimscroll/jquery.slimscroll.min.js',
'main/webapp/bower_components/textAngular/dist/textAngular.min.js',
'main/webapp/bower_components/venturocket-angular-slider/build/angular-slider.js',
'main/webapp/bower_components/videogular/videogular.js',
'main/webapp/bower_components/videogular-buffering/buffering.js',
'main/webapp/bower_components/videogular-controls/controls.js',
'main/webapp/bower_components/videogular-ima-ads/ima-ads.js',
'main/webapp/bower_components/videogular-overlay-play/overlay-play.js',
'main/webapp/bower_components/videogular-poster/poster.js',
'main/webapp/bower_components/waves/dist/waves.min.js',
'main/webapp/bower_components/angular-mocks/angular-mocks.js',
// endbower
'main/webapp/scripts/app/app.js',
'main/webapp/scripts/app/**/*.+(js|html)',
'main/webapp/scripts/components/**/*.+(js|html)',
'test/javascript/spec/helpers/module.js',
'test/javascript/spec/helpers/httpBackend.js',
'test/javascript/**/!(karma.conf|protractor.conf).js'
],
// list of files / patterns to exclude
exclude: ['test/javascript/e2e/**'],
preprocessors: {
'./main/webapp/scripts/**/*.js': ['coverage'],
'**/*.html': ['ng-html2js']
},
reporters: ['dots', 'jenkins', 'coverage', 'progress'],
jenkinsReporter: {
outputFile: '../build/test-results/karma/TESTS-results.xml'
},
coverageReporter: {
dir: '../build/test-results/coverage',
reporters: [
{type: 'lcov', subdir: 'report-lcov'}
]
},
// web server port
port: 9876,
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true,
// to avoid DISCONNECTED messages when connecting to slow virtual machines
browserDisconnectTimeout : 10000, // default 2000
browserDisconnectTolerance : 1, // default 0
browserNoActivityTimeout : 4*60*1000 //default 10000
});
};
最近几天我一直在写单元测试,因为我发现它们很混乱而且不像 Java 中那样简单。将不胜感激。
The above expectation doesn't work because $scope.countries is undefined
^^ 这不是真的。不是 $scope.countries 未定义,而是 result
未定义,也不是您要分配给 $scope.countries
的 result
,而是与 $scope.timezones
我认为这是你的问题:
MockTimezone.getTimezones.and.returnValue($q.resolve());
您将 undefined 隐式传递给 resolve()
函数,这会在您实例化控制器时引发错误。
它会抛出该错误,因为您在控制器的末尾有这一行:
$scope.loadTimezones();
正是出于这个原因,我停止了在它们内部初始化控制器。现在我使用从 HTML 启动的 ng-init 来完成它。如果你和我一样修改,以后就不会再遇到这样的问题了。