我正在为当前正在开发的应用开发测试。 应用使用AngularJS 1.5.8,测试使用Karma和Jasmine。
我正在尝试测试面包屑模块,该模块包含以下元素:
breadcrumbs.controller.js
:
class BreadcrumbsController {
constructor($rootScope, $state, Menu) {
'ngInject';
this.$state = $state;
this.Menu = Menu;
this.menuObject = '';
this.show = false;
this.updatePath();
$rootScope.$on('$stateChangeSuccess', () => { this.updatePath(); });
}
updatePath() {
this.showBreadcrumbs();
if(this.Menu.getMenu()) {
this.menuObject = this.Menu.getBreadcrumbs(this.$state.current.name);
}
}
getSref(index) {
let res = ['app'];
res = res.concat(this.menuObject.slice(0, index + 1));
return res.join('.');
}
showBreadcrumbs() {
if(this.$state.current.name != 'login' && this.$state.current.name != 'logout') {
this.show = true;
} else {
this.show = false;
}
}
}
export default BreadcrumbsController;
breadcrumbs.component.js
:
import templateUrl from './breadcrumbs.html';
import controller from './breadcrumbs.controller';
import './breadcrumbs.less';
let breadcrumbsComponent = {
restrict: 'E',
bindings: {},
templateUrl,
controller,
controllerAs: 'vm'
};
export default breadcrumbsComponent;
breadcrumbs.html:
<div ng-if="vm.show">
<ol class="breadcrumb">
<li ng-repeat="menuItem in vm.menuObject track by $index">
<a href ui-sref="{{vm.getSref($index)}}" ng-if="!$last">{{menuItem | translate}}</a>
<span ng-if="$last">{{menuItem | translate}}</span>
</li>
</ol>
</div>
和breadcrumbs.js
作为整个模块加载器:
import angular from 'angular';
import breadcrumbsComponent from './breadcrumbs.component';
let breadcrumbsModule = angular.module('breadcrumbs', [])
.component('breadcrumbs', breadcrumbsComponent);
export default breadcrumbsModule;
使用breadcrumbs.spec.js
测试:
import BreadcrumbsModule from './breadcrumbs'
import BreadcrumbsController from './breadcrumbs.controller';
import BreadcrumbsComponent from './breadcrumbs.component';
import BreadcrumbsTemplate from './breadcrumbs.html';
describe('Breadcrumbs', () => {
let $rootScope, makeController;
beforeEach(window.module(BreadcrumbsModule.name));
beforeEach(inject((_$rootScope_) => {
$rootScope = _$rootScope_.$new();
makeController = () => {
return new BreadcrumbsController();
};
}));
describe('Module', () => {
// top-level specs: i.e., routes, injection, naming
});
describe('Controller', () => {
// controller specs
it('has a show property', () => {
let controller = makeController();
expect(controller).to.have.property('show');
});
});
describe('Template', () => {
// template specs
// tip: use regex to ensure correct bindings are used e.g., {{ }}
it('has show variable in template', () => {
expect(BreadcrumbsTemplate).to.match(/{{\s?vm\.show\s?}}/g);
});
});
describe('Component', () => {
// component/directive specs
let component = BreadcrumbsComponent;
it('includes the intended template',() => {
expect(component.template).to.equal(BreadcrumbsTemplate);
});
it('uses `controllerAs` syntax', () => {
expect(component).to.have.property('controllerAs');
});
it('invokes the right controller', () => {
expect(component.controller).to.equal(BreadcrumbsController);
});
});
});
在运行测试时-我得到了更多模块的测试,这些模块在spec.bundle.js中被引用-我收到错误:
Breadcrumbs
Component
× invokes the right controller
TypeError: Unable to get property 'equal' of undefined or null reference
error properties: Object({ number: -2146823281 })
at <Jasmine>
at Anonymous function (webpack:///client/app/common/breadcrumbs/breadcrumbs.spec.js:50:8
<- spec.bundle.js:35968:7)
at <Jasmine>
× uses `controllerAs` syntax
TypeError: Unable to get property 'have' of undefined or null reference
error properties: Object({ number: -2146823281 })
at <Jasmine>
at Anonymous function (webpack:///client/app/common/breadcrumbs/breadcrumbs.spec.js:46:8
<- spec.bundle.js:35964:7)
at <Jasmine>
× includes the intended template
TypeError: Unable to get property 'equal' of undefined or null reference
error properties: Object({ number: -2146823281 })
at <Jasmine>
at Anonymous function (webpack:///client/app/common/breadcrumbs/breadcrumbs.spec.js:42:8
<- spec.bundle.js:35960:7)
at <Jasmine>
Template
× has show variable in template
TypeError: Unable to get property 'match' of undefined or null reference
error properties: Object({ number: -2146823281 })
at <Jasmine>
at Anonymous function (webpack:///client/app/common/breadcrumbs/breadcrumbs.spec.js:33:6
<- spec.bundle.js:35951:7)
at <Jasmine>
Controller
× has a show property
TypeError: Unable to get property 'current' of undefined or null reference
error properties: Object({ number: -2146823281 })
at <Jasmine>
at showBreadcrumbs (webpack:///client/app/common/breadcrumbs/breadcrumbs.controller.js:30
:4 <- spec.bundle.js:638:7)
at updatePath (webpack:///client/app/common/breadcrumbs/breadcrumbs.controller.js:16:4 <-
spec.bundle.js:622:7)
at BreadcrumbsController (webpack:///client/app/common/breadcrumbs/breadcrumbs.controller
.js:10:4 <- spec.bundle.js:612:5)
at makeController (webpack:///client/app/common/breadcrumbs/breadcrumbs.spec.js:13:6 <- s
pec.bundle.js:35931:7)
at Anonymous function (webpack:///client/app/common/breadcrumbs/breadcrumbs.spec.js:24:6
<- spec.bundle.js:35942:7)
at <Jasmine>
很明显,好像模块的控制器没有被实例化,是未定义的,未被调用,因为$state
对象没有被注入。
但是当我尝试将uiRouter和Menu服务注入breadcrumbs.spec.js
内时,像这样:
[...]
import uiRouter from 'angular-ui-router';
import Menu from '../menu/menu.js';
[...]
beforeEach(window.module(uiRouter));
beforeEach(window.module(Menu));
beforeEach(inject((_$rootScope_, uiRouter, Menu) => {
$rootScope = _$rootScope_.$new();
makeController = () => {
return new BreadcrumbsController();
};
}));
我也得到:
错误:[$ injector:unpr]未知提供程序:uiRouterProvider <-uiRouter` 错误。
我真的不知道问题出在哪里。
有什么想法吗?