Angular2 Material md-sidenav-container在ng测试中导致异常

时间:2017-02-20 13:32:57

标签: angular-material

在新的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);
  }
}

1 个答案:

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