2016-05-20 8 views
5

私はng2テストを書いていますが、テストのためにルータを自分のコンポーネントに注入する際に問題が発生しています。私のコンポーネントのコンストラクタは、1つの引数、つまりprivate router: Routerをとります。Angular2 RC.1 - ルータをユニットテストに注入

しかし、テストケースを実行すると、ルーターを注入しようとしているときにエラーが発生します。私は間違って何をしていますか?誰かが実用的な例を提供できますか?ここでNo provider for ComponentResolver! (Router -> ComponentResolver)

は私のテストです:私はangular2-RC.1ここ

を使用してい

は私が取得していますエラーです

import {describe, it, expect, beforeEach, afterEach, beforeEachProviders, inject} from "@angular/core/testing"; 
import {ReflectiveInjector, provide} from "@angular/core"; 
import {HTTP_PROVIDERS} from "@angular/http"; 
import {Router, ROUTER_PROVIDERS} from "@angular/router"; 
import {ROUTER_FAKE_PROVIDERS} from "@angular/router/testing"; 
import {Location} from "@angular/common"; 
import {SpyLocation} from "@angular/common/testing/location_mock"; 
import {Observable} from "rxjs/Observable"; 
import {MyComp} from "./MyComp"; 

describe("MyComp",() => { 

    let injector: ReflectiveInjector, 
     myComp: MyComp, 
     router: Router; 

    beforeEach(() => { 

    injector = ReflectiveInjector.resolveAndCreate([   
     HTTP_PROVIDERS, 
     ROUTER_FAKE_PROVIDERS,   
     provide(Location, {useClass: SpyLocation}) 

    ]); 

    router = injector.get(Router); 
    myComp = new MyComp(router); 


    });  

    afterEach(() => { 
    injector = null;  
    myComp = null; 
    router = null; 
    }); 

    it("should be defined",() => { 

    expect(myComp).toBeDefined(); 

    }); 



}); 

答えて

10

あなたは、ルータのジャスミンのスパイオブジェクトを作成する必要があります。 AppComponentには、ルータを取り込むコンストラクタがあります。

import { AppComponent } from './app.component'; 
import {Router, ROUTER_PROVIDERS} from "@angular/router"; 

describe('app component',() => { 
    let component: AppComponent; 
    let router: Router; 
    beforeAll(() => { 
     router = jasmine.createSpyObj("Router", ['navigate']); 
     component = new AppComponent(router); 
    }); 
    it("should be defined",() => { 
     expect(component).toBeDefined(); 
    }); 
}); 
+0

答えがとてもシンプルで見えない時があります。 **(facepalm)**。これは素晴らしい!シンプルでしかも効果的なソリューション!ありがとうございました! – hartpdx

+0

ニースのソリューション、ありがとう! –

1

いくつかの変更...これを簡単な解決策は私のために働く:

import {MyComp} from "./MyComp"; 
import {RootRouter} from 'angular2/src/router/router'; 
import {provide} from 'angular2/core'; 
import {Router} from 'angular2/router'; 

describe("MyComp",() => { 
    let myComp: MyComp, 
    router; 

beforeEach(() => { 
    provide(Router, {useClass: RootRouter}) 
    myComp = new MyComp(router); 
}) 

it("should be defined",() => { 
    expect(myComp).toBeDefined(); 
    }); 
}); 
+3

が、これはうまく働いているだろう。私は** RCを使用しています。1 **バージョンのRootRouterオブジェクトがもう存在しない場合(または存在する場合は、どこに配置されているかわかりません) – hartpdx

0

さて、私は解決策を思いついた。それは理想的ではありませんが、機能します。基本的には、私が必要とするメソッドを実装するMockRouterクラスを作成しています。

MockRouter:

export class MockRouter { 

    public navigate() { 
     console.log(“Mock router was called.”); 
    } 

} 

さて、私のテストケースでは、私がしなければならないすべては、ルータのモック実装を提供します

provide(Router, {useClass: MockRouter})

それは次のようになり本当にあなたのジャスミンテストケースにRouterを適切に注入する方法をNG2のドキュメントに示すといいですね。彼らのオブジェクトを嘲笑は、それが不必要なステップでなければならないようだ。

(ちなみに、私はROUTER_FAKE_PROVIDERSを使用してみましたし、今でも上記ComponentResolverエラーを得た)

0

はここで少し冗長ですが、 は、私たちは、ルートの変更をチェックするために、SpyLocationを使用することができます代替ソリューションです。 まず、汎用テストルータプロバイダを作成します。

ルータテストproviders.ts

import { ComponentResolver } from '@angular/core'; 
import { Type } from '@angular/core/src/facade/lang'; 
import { SpyLocation } from '@angular/common/testing'; 
import { Location } from '@angular/common'; 
import { Router, RouterOutletMap } from '@angular/router'; 
import { RouteSegment } from '@angular/router/src/segments'; 
import { RouterUrlSerializer, DefaultRouterUrlSerializer } from '@angular/router/src/router_url_serializer'; 
/** 
* this class provides the means of loading the tested component type 
*/ 
export class FakeRootComponentLoader { 
    constructor(private rootComponentType: Type) { 
     this.rootComponentType = rootComponentType; 
    } 
    public getRootComponentType =() => { 
     return this.rootComponentType; 
    } 
} 

let routerFactory = function (
     fakeRootComponentLoader: FakeRootComponentLoader, 
     componentResolver: ComponentResolver, 
     urlSerializer: RouterUrlSerializer, 
     routerOutletMap: RouterOutletMap, 
     location: Location): Router 
{ 
    let fakeRootComponentType = fakeRootComponentLoader.getRootComponentType(); 
    /** 
    * _rootComponent should not be null, but it is what in angular2 rc.1 code 
    * so we replicate the behaviour 
    */ 
    return new Router(
     null, 
     fakeRootComponentType, 
     componentResolver, 
     urlSerializer, 
     routerOutletMap, 
     location); 
}; 

export const ROUTER_TEST_PROVIDERS: any[] = [ 
    {provide: RouterUrlSerializer, useClass: DefaultRouterUrlSerializer}, 
    RouterOutletMap, 
    {provide: Location, useClass: SpyLocation}, 
    {provide: RouteSegment, useFactory: (r) => r.routeTree.root, deps: [Router]}, 
    { 
    provide: Router, 
    useFactory: routerFactory, 
    deps: [FakeRootComponentLoader, ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location] 
    } 
]; 

対応ジャスミン試験を以下に提供されます。

navigation.spec.ts匿名ES 6クラスとjasmineを使用して

import { Component } from '@angular/core'; 
import { beforeEach, beforeEachProviders, inject } from '@angular/core/testing'; 
import { ROUTER_DIRECTIVES, Route, Routes, Router } from '@angular/router'; 
import { TestComponentBuilder } from '@angular/compiler/testing'; 
import { Location } from '@angular/common'; 
import { ROUTER_TEST_PROVIDERS, FakeRootComponentLoader } from './router-test-providers'; 
/** 
* We inject router into the EmptyComponent, 
* Due to the way DI works in angular2, if we import the ROUTER_TEST_PROVIDERS, 
* and inject the Router, we will get our own implementation of the Router injected. 
*/ 
@Component({selector: 'empty-component', template: `empty`}) 
@Component({ 
    selector: 'empty-component', 
    template: `empty`, 
    directives: [ROUTER_DIRECTIVES] 
}) 
class EmptyComponent { 
    constructor (private router: Router){ } 
    public getRouter() {return this.router;} 
} 

@Component({ 
    selector: 'root-component', 
    template: `<router-outlet></router-outlet>`, 
    directives: [ROUTER_DIRECTIVES] 
}) 
@Routes([new Route({path: '/login', component: EmptyComponent})]) 
class RootComponent { } 
describe('navigation',() => { 
    beforeEachProviders(() => [ 
     { 
      provide: FakeRootComponentLoader, 
      useFactory:() => new FakeRootComponentLoader(RootComponent) 
     }, 
     ROUTER_TEST_PROVIDERS, 
     EmptyComponent 
    ]); 


    let location: Location; 
    let testCb: TestComponentBuilder; 
    let emptyComp: EmptyComponent; 
    beforeEach(inject([Location, TestComponentBuilder, EmptyComponent], (loc, tcb, emptyCt) => { 
     location = loc; 
     testCb = tcb; 
     emptyComp = emptyCt; 

    })); 

    it('should be defined',() => { 
     expect(EmptyComponent).toBeDefined(); 
    }); 

    it('Should navigate to login', (done) => { 
     expect(location.path()).toEqual(''); 
     testCb.createAsync(RootComponent).then(fixture => { 
      emptyComp.getRouter().navigate(['login']).then(() => { 
       fixture.detectChanges(); 
       expect(location.path()).toBe('/login'); 
       done(); 
      }).catch(e => done.fail(e)); 
     }); 
    }); 
}); 
2

:angular2の**ベータ**バージョンの

beforeEach(() => addProviders([ 
{ 
    provide: Router, 
    useClass: class { navigate = jasmine.createSpy("navigate"); } 
}])); 
+0

感謝!これは私のために、百の​​異なる例を試した後に働いた – ganjan

関連する問題