2016-10-05 6 views
3

Ich habe eine Weile damit verbracht, die Module in Angular2 zu bekommen und mag sie wirklich, aber ich bin ein wenig unsicher, beide Ansätze zu testen meine Module und die darin enthaltenen Komponenten. (Ich weiß auch, dass mein app.component kann und wahrscheinlich mehr ausgebrochen jetzt werden soll, aber es ist hilfreich, während das Erlernen der Test-Framework ein wenig komplexer zu sein)Wie soll ich Einheit Angular2 Komponenten und Module testen, die andere Module (und Komponenten) importiert hat

Zum Beispiel das ist mein app.module:

import { createStore, compose, applyMiddleware } from 'redux'; 
import ReduxThunk from 'redux-thunk'; 
import { AUTH_PROVIDERS } from 'angular2-jwt'; 

import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { FormsModule } from '@angular/forms'; 

import { ComponentsModule } from './components'; 
import { MaterialModule} from './material'; 
import { RouterModule } from '@angular/router'; 

import { AppComponent } from './app.component'; 
import { ViewsModule } from './+views'; 

import { rootReducer } from './dataStore'; 

import { CurrentUserModel } from './models/current-user' 


const appStore = createStore(rootReducer, applyMiddleware(ReduxThunk)); 

const APP_DECLARATIONS = [ 
    AppComponent 
]; 

const APP_PROVIDERS = [ 
    { provide: 'AppStore', useValue: appStore }, 
    CurrentUserModel 
]; 

@NgModule({ 
    imports:[ 
    FormsModule, 
    BrowserModule, 
    RouterModule,// here as well as in our Views Module because of router-outlet 
    ViewsModule, 
    MaterialModule, // here as well as in our Views & componet Module because used in App componet 
    ComponentsModule 
    ], 
    declarations: APP_DECLARATIONS, 
    bootstrap:[AppComponent], 
    providers: APP_PROVIDERS, 
}) 
export class AppModule { 

} 

und das ist, was mein app.component wie folgt aussieht:

import { Component, ViewChild, AfterViewInit } from '@angular/core'; 

import { Router } from '@angular/router'; 

@Component({ 
    selector: 'app', 
    styleUrls:['app.component.scss'], 
    template: ` 
    <md-toolbar> 
    <!-- <i class="material-icons demo-toolbar-icon">menu</i> --> 
    <span class="toolbar-brand">Franks</span> 
    <span *ngIf="searchActive" role="search" class="fill-remaining-space"> 
     <span class="search-input-container flex flex-1"> 
      <i class="material-icons search-link">search</i> 
      <input class="search-input" placeholder="Search" type="text" id="searchInput" #searchInput (keyup.esc)="exitSearch($event)"/> 
     </span> 
    </span> 
    <i *ngIf="searchActive" class="material-icons right selectable" (click)="exitSearch($event)">close</i> 

    <span *ngIf="!searchActive" class="fill-remaining-space"> 

    </span> 
    <span *ngIf="!searchActive" role="navmenu"> 
     <span class="hlink" routerLink="/" routerLinkActive="active">home</span> 
     <span class="hlink" routerLink="/profile" routerLinkActive="active">Profile</span> 
     <span class="hlink" routerLink="/login" routerLinkActive="active">Login</span> 
     <span class="hlink" routerLink="/signup" routerLinkActive="active">Sign Up</span> 
     <i class="material-icons search-link" (click)="activeSearch($event)">search</i> 
    </span> 
    </md-toolbar> 
    <div class="container"> 
    <router-outlet></router-outlet> 
    </div> 
    `, 
}) 
export class AppComponent { 
    @ViewChild('searchInput') searchInputRef; 

    ngAfterViewChecked() { 
    if(this.searchActive && this.searchInputRef){ 
     console.log(this.searchInputRef);  
     this.searchInputRef.nativeElement.focus(); 
    } 
    } 
    searchActive: boolean; 
    constructor(public router: Router) { 
    this.searchActive = false; 
    } 

    activeSearch(event):void { 
    this.searchActive = true; 
    } 

    exitSearch(event) : void { 
    this.searchActive = false; 
    } 
} 

So weiß ich, dass ich möglicherweise die Komponenten all verspotten kann mit zum Beispiel des MaterialComponents (dies ist nur ein Wrapper-Modul für die Materialkomponenten) in meinen Tests, aber das scheint ein wenig langweilig. Ist das meine einzige Option und wenn ja, macht es Sinn, das Erstellen eines Mocks von Komponenten beim Erstellen der Komponenten Teil des Prozesses zu machen.

zu Informationszwecken ist das, was mein Material Modul aussieht und meine Ansichten und Komponenten Module sind ähnlich:

import { NgModule } from '@angular/core'; 

// Material 
import { MdCardModule } from '@angular2-material/card'; 
import { MdButtonModule } from '@angular2-material/button'; 
import { MdInputModule } from '@angular2-material/input'; 
import { MdToolbarModule } from '@angular2-material/toolbar'; 
import { MdListModule } from '@angular2-material/list'; 
import { MdIconModule, MdIconRegistry } from '@angular2-material/icon'; 



const MATERIAL_UI_MODULES = [ 
    MdCardModule, 
    MdButtonModule, 
    MdInputModule, 
    MdToolbarModule, 
    MdIconModule, 
    MdListModule 
] 
const MATERIAL_UI_REGISTRIES = [ 
    MdIconRegistry 
] 

@NgModule({ 
    imports:[ 
    ...MATERIAL_UI_MODULES, 
    ], 
    providers: MATERIAL_UI_REGISTRIES, 
    exports:[ 
    ...MATERIAL_UI_MODULES, 
    ] 
}) 
export class MaterialModule { 

} 

Antwort

1

So schließlich habe ich herausgefunden, wie dies zu tun, und das ist meine aktuelle Lösung:

/* tslint:disable:no-unused-variable */ 
import { TestBed, inject, async } from '@angular/core/testing'; 
import { RouterTestingModule } from '@angular/router/testing'; 
import { By } from '@angular/platform-browser'; 

import { Component,ViewChild, AfterViewChecked } from '@angular/core'; 
import { Router } from '@angular/router'; 
import { Location, CommonModule } from '@angular/common'; 
import { MaterialModule} from './material'; 

@Component({ 
    template: '<div></div>' 
}) 
class DummyComponent { 
} 


import { AppComponent } from './app.component'; 

describe('component: TestComponent', function() { 
    beforeEach(() => { 
    TestBed.configureTestingModule({ 
     imports: [ 
     CommonModule, 
     RouterTestingModule.withRoutes([ 
     { path: 'profile', component: DummyComponent }, 
     { path: 'login', component: DummyComponent }, 
     { path: 'signup', component: DummyComponent }, 
     { path: '', component: DummyComponent } 
     ]), 
     MaterialModule 
     ], 
     declarations: [ AppComponent, DummyComponent ] 
    }); 
    }); 

    it('should create the app', async(() => { 
    let fixture = TestBed.createComponent(AppComponent); 
    let app = fixture.debugElement.componentInstance; 
    expect(app).toBeTruthy(); 
    })); 

    it('should be navigate to correct url for each option in navmenu', 
    async(inject([Router, Location], (router: Router, location: Location) => { 

    let fixture = TestBed.createComponent(AppComponent); 
    fixture.detectChanges(); 

    fixture.debugElement.query(By.css('span.hlink[routerLink="/profile"]')).nativeElement.click(); 
    fixture.whenStable().then(() => { 
     expect(location.path()).toEqual('/profile'); 
     expect(fixture.debugElement.query(By.css('span.hlink[routerLink="/profile"]')).classes['active']).toBeTruthy(); 
     expect(fixture.debugElement.nativeElement.querySelectorAll('span.hlink.active').length).toEqual(1) 

     fixture.debugElement.query(By.css('span.hlink[routerLink="/login"]')).nativeElement.click(); 
     return fixture.whenStable(); 
    }).then(() => { 
     expect(location.path()).toEqual('/login'); 
     expect(fixture.debugElement.query(By.css('span.hlink[routerLink="/login"]')).classes['active']).toBeTruthy(); 
     expect(fixture.debugElement.nativeElement.querySelectorAll('span.hlink.active').length).toEqual(1) 

     fixture.debugElement.query(By.css('span.hlink[routerLink="/signup"]')).nativeElement.click(); 
     return fixture.whenStable(); 
    }).then(() => { 
     expect(location.path()).toEqual('/signup'); 
     expect(fixture.debugElement.query(By.css('span.hlink[routerLink="/signup"]')).classes['active']).toBeTruthy(); 
     expect(fixture.debugElement.nativeElement.querySelectorAll('span.hlink.active').length).toEqual(1) 

     fixture.debugElement.query(By.css('span.hlink[routerLink="/"]')).nativeElement.click(); 
     return fixture.whenStable(); 
    }).then(() => { 
     expect(location.path()).toEqual('/'); 
     expect(fixture.debugElement.query(By.css('span.hlink[routerLink="/"]')).classes['active']).toBeTruthy(); 
     expect(fixture.debugElement.nativeElement.querySelectorAll('span.hlink.active').length).toEqual(1) 
    }); 

    }))); 
}); 
Verwandte Themen