2016-05-20 21 views
5

Tôi đang viết bài kiểm tra ng2 của mình, và tôi đang gặp một số rắc rối khi đưa Bộ định tuyến vào thành phần của tôi để kiểm tra. Hàm khởi tạo cho thành phần của tôi chỉ nhận một đối số-- private router: Router.Angular2 RC.1 - Tiêm Router vào thử nghiệm đơn vị

Tuy nhiên, khi tôi chạy trường hợp thử nghiệm của mình, tôi gặp lỗi khi đang cố gắng tiêm Bộ định tuyến. Tôi đang làm gì sai? Bất cứ ai có thể cung cấp một ví dụ làm việc?

Tôi đang sử dụng angular2-RC.1

Đây là lỗi tôi nhận được: No provider for ComponentResolver! (Router -> ComponentResolver)

Dưới đây là thử nghiệm của tôi:

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(); 

    }); 



}); 

Trả lời

10

Bạn cần phải tạo một đối tượng hoa nhài gián điệp cho router. AppComponent có một hàm tạo trong Bộ định tuyến.

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

Có những lúc câu trả lời đơn giản đến mức bạn không thể nhìn thấy nó. ** (facepalm) **. Điều đó thật tuyệt! Giải pháp đơn giản nhưng hiệu quả! Cảm ơn bạn! – hartpdx

+0

Giải pháp tốt, cảm ơn! –

1

Một số thay đổi ... Đây giải pháp đơn giản phù hợp với tôi:

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

Đối với ** beta ** phiên bản của angular2, điều này sẽ làm việc tốt. Tôi đang sử dụng ** RC.1 ** phiên bản mà đối tượng RootRouter không tồn tại nữa (hoặc nếu có, tôi không biết vị trí của nó nằm ở đâu). – hartpdx

0

Vâng, tôi đã đưa ra một giải pháp. Nó không lý tưởng, nhưng nó hoạt động. Về cơ bản, tôi đang tạo ra một lớp học MockRouter thực hiện các phương pháp tôi cần.

MockRouter:

export class MockRouter { 

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

} 

Bây giờ, trong trường hợp thử nghiệm của tôi, tất cả tôi phải làm là cung cấp cho việc thực hiện mô hình cho router:

provide(Router, {useClass: MockRouter})

Sẽ thực sự tốt đẹp nếu các tài liệu NG2 sẽ cho bạn thấy cách bạn có thể tiêm Router vào các trường hợp thử nghiệm Jasmine của bạn đúng cách. Mocking đồ vật của họ có vẻ như nó phải là một bước không cần thiết.

(FYI, tôi đã cố gắng sử dụng ROUTER_FAKE_PROVIDERS và vẫn có những lỗi ComponentResolver trên)

0

Dưới đây là một giải pháp thay thế đó là một chút dài dòng hơn nhưng cho phép chúng ta sử dụng SpyLocation để kiểm tra những thay đổi lộ trình. Trước tiên, chúng tôi tạo các nhà cung cấp bộ định tuyến thử nghiệm chung.

Router-test-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] 
    } 
]; 

Các thử nghiệm hoa nhài tương ứng được cung cấp dưới đây.

navigation.spec.ts

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

Sử dụng nặc danh ES 6 lớp và jasmine:

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

CẢM ƠN! điều này làm việc cho tôi, sau khi thử một trăm ví dụ khác nhau – ganjan

Các vấn đề liên quan