在新的ng cli项目中基本使用md-sidenav-container会导致第二次及以后的测试中的ng测试失败。
异常
TypeError: Cannot read property 'unsubscribe' of undefined
at ScrollDispatcher.deregister (webpack:///~/@angular/material/core/overlay/scroll/scroll-dispatcher.js:52:0 <- src/test.ts:10756:50)
at Scrollable.ngOnDestroy (webpack:///~/@angular/material/core/overlay/scroll/scrollable.js:28:0 <- src/test.ts:86637:22)
at Wrapper_Scrollable.ngOnDestroy (/OverlayModule/Scrollable/wrapper.ngfactory.js:13:16)
at CompiledTemplate.proxyViewClass.View_MdSidenavContainer0.destroyInternal (/MdSidenavModule/MdSidenavContainer/component.ngfactory.js:66:24)
at CompiledTemplate.proxyViewClass.AppView.destroy (webpack:///~/@angular/core/src/linker/view.js:203:0 <- src/test.ts:82496:14)
at CompiledTemplate.proxyViewClass.DebugAppView.destroy (webpack:///~/@angular/core/src/linker/view.js:606:0 <- src/test.ts:82899:38)
at CompiledTemplate.proxyViewClass.View_AppComponent0.destroyInternal (/DynamicTestModule/AppComponent/component.ngfactory.js:115:19)
at CompiledTemplate.proxyViewClass.AppView.destroy (webpack:///~/@angular/core/src/linker/view.js:203:0 <- src/test.ts:82496:14)
at CompiledTemplate.proxyViewClass.DebugAppView.destroy (webpack:///~/@angular/core/src/linker/view.js:606:0 <- src/test.ts:82899:38)
at CompiledTemplate.proxyViewClass.View_AppComponent_Host0.destroyInternal (/DynamicTestModule/AppComponent/host.ngfactory.js:33:19)
at CompiledTemplate.proxyViewClass.AppView.destroy (webpack:///~/@angular/core/src/linker/view.js:203:0 <- src/test.ts:82496:14)
at CompiledTemplate.proxyViewClass.DebugAppView.destroy (webpack:///~/@angular/core/src/linker/view.js:606:0 <- src/test.ts:82899:38)
at CompiledTemplate.proxyViewClass.AppView.detachAndDestroy (webpack:///~/@angular/core/src/linker/view.js:187:0 <- src/test.ts:82480:14)
at ComponentRef_.destroy (webpack:///~/@angular/core/src/linker/component_factory.js:147:51 <- src/test.ts:40464:70)
at ComponentFixture.destroy (webpack:///~/@angular/core/bundles/core-testing.umd.js:263:0 <- src/test.ts:21186:35)
app.component.html
<div>
<md-sidenav-container>
<md-sidenav mode="side" opened="true">Drawer content</md-sidenav>
<div class="my-content">Main content</div>
</md-sidenav-container>
</div>
app.component.spec.ts
import {TestBed, async} from '@angular/core/testing';
import {MaterialModule} from '@angular/material';
import {AppComponent} from './app.component';
import 'hammerjs';
describe('AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
MaterialModule
],
declarations: [
AppComponent
],
});
TestBed.compileComponents();
});
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
// Same test repeated enough to generate exception
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});
package.json (默认+材料2.0.0-beta.2)
{
"name": "admin",
"version": "0.0.0",
"license": "MIT",
"angular-cli": {},
"scripts": {
"start": "ng serve",
"lint": "tslint \"src/**/*.ts\"",
"test": "ng test",
"pree2e": "webdriver-manager update",
"e2e": "protractor"
},
"private": true,
"dependencies": {
"@angular/common": "^2.4.0",
"@angular/compiler": "^2.4.0",
"@angular/core": "^2.4.0",
"@angular/forms": "^2.4.0",
"@angular/http": "^2.4.0",
"@angular/platform-browser": "^2.4.0",
"@angular/platform-browser-dynamic": "^2.4.0",
"@angular/material": "^2.0.0-beta.2",
"@angular/router": "^3.4.0",
"core-js": "^2.4.1",
"rxjs": "^5.0.1",
"ts-helpers": "^1.1.1",
"zone.js": "^0.7.2"
},
"devDependencies": {
"@angular/cli": "1.0.0-beta.31",
"@angular/compiler-cli": "^2.4.0",
"@types/jasmine": "2.5.38",
"@types/node": "^6.0.42",
"codelyzer": "~2.0.0-beta.1",
"jasmine-core": "2.5.2",
"jasmine-spec-reporter": "2.5.0",
"karma": "1.2.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-jasmine": "^1.0.2",
"karma-coverage-istanbul-reporter": "^0.2.0",
"protractor": "~5.1.0",
"ts-node": "1.2.1",
"tslint": "^4.3.0",
"typescript": "~2.0.0"
}
}
app.component.ts
import {Component, ElementRef, OnInit} from '@angular/core';
import {HostListener} from '@angular/core/src/metadata/directives';
import {AuthService} from './services/auth.service';
import {ConceptService} from './services/concept.service';
import {AppService} from './services/app.service';
import {Router, NavigationStart} from '@angular/router';
import {LocationService} from './services/location.service';
import {ConfigService} from './services/config.service';
import {ToastService} from './services/toast.service';
import {ContextService} from './services/context.service';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
})
export class AppComponent implements OnInit {
sidenavOpen = true;
appElement;
envName = 'default';
_serverVersion: any = '{}';
currentRoute = '';
menuItems = [
{route: 'home', name: 'Dashboard', icon: 'home'}
// some lines omitted
, {route: 'concepts', name: 'Concepts', icon: 'toc'}
];
constructor(elementRef: ElementRef,
private authService: AuthService,
private conceptService: ConceptService,
private configService: ConfigService,
private locationService: LocationService,
private appService: AppService,
private contextService: ContextService,
private toast: ToastService,
private router: Router) {
this.appElement = elementRef.nativeElement;
}
ngOnInit(): void {
this.appService.container = this.appElement.querySelector('.app-content');
// Warm caches
Promise.all([
this.conceptService.getAll(),
this.configService.getAll(),
this.locationService.getAll(),
this.configService.serverVersion().then(ver => this._serverVersion = ver),
this.contextService.getContext().then(ctx => this.envName = ctx.name.replace(' ', '_').toLowerCase())
]).catch(e => this.toast.error(e));
// Monitor size for handling sidebar
this.onResize(this.appElement.clientWidth);
this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
this.onResize(this.appElement.clientWidth);
}
});
// Log out on closing or or navigating away
window.onbeforeunload = function () {
this.authService.logout();
}.bind(this);
}
@HostListener('window:resize', ['$event.target.innerWidth'])
onResize(w) {
this.sidenavOpen = w > 500;
}
isDisabled(path: string) {
return !this.authService.isAuthorised(path);
}
}
答案 0 :(得分:0)
我确实有同样的问题。我通过为夹具等制作全局vars
来解决它。
fdescribe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let de: DebugElement;
let el: HTMLElement;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
imports:[RouterModule,UiPageHeaderModule,UiAppHeaderModule,RouterTestingModule, MaterialModule.forRoot()],
});
TestBed.compileComponents();
});
it('should create the app', async(() => {
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
// Same test repeated enough to generate exception
it('should create the app', async(() => {
//const fixture = TestBed.createComponent(AppComponent); no need of this. this is causing the issue,
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});