2017-01-20 5 views
2

Testing Suite ist immer noch nicht bereit in ionic 2. Also verwende ich diese tutorial für den Test. Dies verwendet im Wesentlichen angular 2 Testsuite. Hier ist meine test.tsFehler: Kein Anbieter für DeepLinker beim Komponententest

declare var __karma__: any; 
declare var require: any; 

// Prevent Karma from running prematurely. 
__karma__.loaded = function(): void { /* no op */}; 

// First, initialize the Angular testing environment. 
getTestBed().initTestEnvironment(
    BrowserDynamicTestingModule, 
    platformBrowserDynamicTesting(), 
); 
// Then we find all the tests. 
const context: any = require.context('./', true, /\.spec\.ts/); 
// And load the modules. 
context.keys().map(context); 
// Finally, start Karma to run the tests. 
__karma__.start(); 

export class TestUtils { 

    public static beforeEachCompiler(components: Array<any>): Promise<{fixture: any, instance: any}> { 
    return TestUtils.configureIonicTestingModule(components) 
    .compileComponents().then(() => { 
     let fixture: any = TestBed.createComponent(components[0]); 
     return { 
     fixture: fixture, 
     instance: fixture.debugElement.componentInstance, 
     }; 
    }); 
    } 

    public static configureIonicTestingModule(components: Array<any>): typeof TestBed { 
    return TestBed.configureTestingModule({ 
     schemas: [CUSTOM_ELEMENTS_SCHEMA], 
     declarations: [ 
     ...components 
     ], 
     providers: [ 
     NavController,LoadingController,App, Form, Keyboard, DomController, MenuController, 
     { provide: Bookemon, useClass: BookMock}, 
     { provide: Authentication, useClass: AuthMock}, 
     {provide: Storage, useClass: StorageMock}, 
     {provide: Config, useClass: ConfigMock}, 
     {provide: Platform, useClass: PlatformMock}, 
     {provide: Events, useClass: Eventsmock} 
     ], 
     imports: [ 
     FormsModule, 
     IonicModule, 
     ReactiveFormsModule, 
     SwingModule 
     ], 
    }); 
    } 

Ich versuche, meine tab.ts Komponente zu testen.

tab.ts

@Component({ 
    selector: 'page-tabs', 
    templateUrl: 'tabs.html' 
}) 
export class TabsPage { 
    user: any; 
    tab1Root: any = UserHuntsPage; 
    tab2Root: any = HomePage; 
    tab3Root: any = FeedPage; 

    constructor(public navCtrl: NavController , public auth: Authentication ,public events: Events) { 

    } 
    ngOnInit(){ 
    this.events.subscribe('logout-user' ,() => { 
     this.navCtrl.setRoot(WelcomePage); 
    }) 
    } 
} 

Hier ist tab.pec.ts

let fixture: ComponentFixture<TabsPage> = null; 
let instance: any = null; 
describe('Tabs component',()=>{ 
    beforeEach(async(() => TestUtils.beforeEachCompiler([TabsPage]).then(compiled => { 
    fixture = compiled.fixture; 
    instance = compiled.instance; 
    }))); 
    it('initialises',() => { 
    expect(1).toBeTruthy(); 
    }); 
}) 

Wenn ich den Test, den ich diesen Fehler laufen,

Error: No provider for DeepLinker! 
    at NoProviderError.BaseError [as constructor] (webpack:///~/@angular/core/src/facade/errors.js:24:0 <- src/test.ts:8542:34) 
    at NoProviderError.AbstractProviderError [as constructor] (webpack:///~/@angular/core/src/di/reflective_errors.js:41:0 <- src/test.ts:72995:16) 
    at new NoProviderError (webpack:///~/@angular/core/src/di/reflective_errors.js:72:0 <- src/test.ts:73026:16) 
    at ReflectiveInjector_._throwOrNull (webpack:///~/@angular/core/src/di/reflective_injector.js:758:0 <- src/test.ts:119137:19) 
    at ReflectiveInjector_._getByKeyDefault (webpack:///~/@angular/core/src/di/reflective_injector.js:786:0 <- src/test.ts:119165:25) 
    at ReflectiveInjector_._getByKey (webpack:///~/@angular/core/src/di/reflective_injector.js:749:0 <- src/test.ts:119128:25) 
    at ReflectiveInjector_.get (webpack:///~/@angular/core/src/di/reflective_injector.js:558:0 <- src/test.ts:118937:21) 
    at TestBed.get (webpack:///~/@angular/core/bundles/core-testing.umd.js:814:0 <- src/test.ts:39277:67) 
    at CompiledTemplate.proxyViewClass.AppView.injectorGet (webpack:///~/@angular/core/src/linker/view.js:109:0 <- src/test.ts:119679:45) 
    at CompiledTemplate.proxyViewClass.DebugAppView.injectorGet (webpack:///~/@angular/core/src/linker/view.js:351:0 <- src/test.ts:119921:49) 
Error: Uncaught (in promise): Error: Error in ./TabsPage class TabsPage - inline template:0:0 caused by: No provider for DeepLinker! 
    at resolvePromise (webpack:///~/zone.js/dist/zone.js:468:0 <- src/test.ts:141307:31) 
    at resolvePromise (webpack:///~/zone.js/dist/zone.js:453:0 <- src/test.ts:141292:17) 
    at webpack:///~/zone.js/dist/zone.js:502:0 <- src/test.ts:141341:17 
    at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:265:0 <- src/test.ts:141104:35) 
    at ProxyZoneSpec.onInvokeTask (webpack:///~/zone.js/dist/proxy.js:103:0 <- src/test.ts:110667:39) 
    at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:264:0 <- src/test.ts:141103:40) 
    at Zone.runTask (webpack:///~/zone.js/dist/zone.js:154:0 <- src/test.ts:140993:47) 
    at drainMicroTaskQueue (webpack:///~/zone.js/dist/zone.js:401:0 <- src/test.ts:141240:35) 

ich nicht DeepLinker überall in meiner Anwendung verwendet haben. Ich denke, es könnte eine Abhängigkeit von etwas in meinen Anbietern sein. Ich habe viel Zeit damit verbracht und kann nicht verstehen, warum das passiert. Jede Hilfe wäre willkommen.

bearbeiten

Ich habe DeepLinker im providers aber das gibt einen anderen Fehler,

Failed: Can't resolve all parameters for DeepLinker: (?, ?, ?). 
Error: Can't resolve all parameters for DeepLinker: (?, ?, ?). 
    at CompileMetadataResolver._getDependenciesMetadata (webpack:///~/@angular/compiler/src/metadata_resolver.js:623:0 <- src/test.ts:50686:19) 
    at CompileMetadataResolver._getTypeMetadata (webpack:///~/@angular/compiler/src/metadata_resolver.js:517:0 <- src/test.ts:50580:26) 
    at webpack:///~/@angular/compiler/src/metadata_resolver.js:667:0 <- src/test.ts:50730:41 
    at Array.forEach (native) 
    at CompileMetadataResolver._getProvidersMetadata (webpack:///~/@angular/compiler/src/metadata_resolver.js:647:0 <- src/test.ts:50710:19) 
    at CompileMetadataResolver._loadNgModuleMetadata (webpack:///~/@angular/compiler/src/metadata_resolver.js:430:0 <- src/test.ts:50493:50) 
    at CompileMetadataResolver.loadNgModuleMetadata (webpack:///~/@angular/compiler/src/metadata_resolver.js:313:0 <- src/test.ts:50376:29) 
    at RuntimeCompiler._loadModules (webpack:///~/@angular/compiler/src/runtime_compiler.js:99:0 <- src/test.ts:69258:41) 
    at RuntimeCompiler._compileModuleAndAllComponents (webpack:///~/@angular/compiler/src/runtime_compiler.js:83:0 <- src/test.ts:69242:35) 
    at RuntimeCompiler.compileModuleAndAllComponentsAsync (webpack:///~/@angular/compiler/src/runtime_compiler.js:65:0 <- src/test.ts:69224:21) 

bearbeiten

Zugabe von Anbietern wie { provide: DeepLinker, useValue: {} } Ergebnisse in neuer Fehler,

TypeError: this.parent.registerChildNav is not a function 
    at new Tabs (webpack:///~/ionic-angular/components/tabs/tabs.js:173:0 <- src/test.ts:46470:25) 
    at new Wrapper_Tabs (/IonicModule/Tabs/wrapper.ngfactory.js:7:18) 
    at CompiledTemplate.proxyViewClass.View_TabsPage0.createInternal (/DynamicTestModule/TabsPage/component.ngfactory.js:27:20) 
    at CompiledTemplate.proxyViewClass.AppView.create (webpack:///~/@angular/core/src/linker/view.js:74:0 <- src/test.ts:119644:21) 
    at CompiledTemplate.proxyViewClass.DebugAppView.create (webpack:///~/@angular/core/src/linker/view.js:330:0 <- src/test.ts:119900:44) 
    at CompiledTemplate.proxyViewClass.View_TabsPage_Host0.createInternal (/DynamicTestModule/TabsPage/host.ngfactory.js:16:19) 
    at CompiledTemplate.proxyViewClass.AppView.createHostView (webpack:///~/@angular/core/src/linker/view.js:81:0 <- src/test.ts:119651:21) 
    at CompiledTemplate.proxyViewClass.DebugAppView.createHostView (webpack:///~/@angular/core/src/linker/view.js:341:0 <- src/test.ts:119911:52) 
    at ComponentFactory.create (webpack:///~/@angular/core/src/linker/component_factory.js:154:0 <- src/test.ts:54276:25) 
    at initComponent (webpack:///~/@angular/core/bundles/core-testing.umd.js:852:0 <- src/test.ts:39321:53) 
Error: Uncaught (in promise): Error: Error in ./TabsPage class TabsPage - inline template:0:0 caused by: this.parent.registerChildNav is not a function 
    at resolvePromise (webpack:///~/zone.js/dist/zone.js:468:0 <- src/test.ts:141416:31) 
    at resolvePromise (webpack:///~/zone.js/dist/zone.js:453:0 <- src/test.ts:141401:17) 
    at webpack:///~/zone.js/dist/zone.js:502:0 <- src/test.ts:141450:17 
    at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:265:0 <- src/test.ts:141213:35) 
    at ProxyZoneSpec.onInvokeTask (webpack:///~/zone.js/dist/proxy.js:103:0 <- src/test.ts:110667:39) 
    at ZoneDelegate.invokeTask (webpack:///~/zone.js/dist/zone.js:264:0 <- src/test.ts:141212:40) 
    at Zone.runTask (webpack:///~/zone.js/dist/zone.js:154:0 <- src/test.ts:141102:47) 
    at drainMicroTaskQueue (webpack:///~/zone.js/dist/zone.js:401:0 <- src/test.ts:141349:35) 

Antwort

2

Sie haben Recht, es ist wahrscheinlich eine Abhängigkeit von einer der Komponenten. Haben Sie versucht, die DeepLinker zum TestBed wie diese bieten:

TestBed.configureTestingModule({ 
     ... 
     providers: [ 
     { provide: DeepLinker, useValue: {} }, 
     ... // the usual stuff 

Bearbeiten zur letzten Fehler:

TestBed.configureTestingModule({ 
     ... 
     providers: [ 
     DeepLinker, 
     ... // the usual stuff 

Wenn es wirklich nicht nötig, können Sie die Funktionalität von ihm leicht und entfernen konnte:

Wenn Sie den DeepLinker auf diese Weise bereitstellen, wird die tatsächliche DeepLinker-Implementierung erfolgreich mit einem leeren Objekt instanziiert und überschrieben. Ein Teil der Anwendung erfordert jedoch die fehlende registerChildNav Methode. Am besten erstellen Sie diese Methode für das Objekt, mit dem Sie die ursprüngliche DeepLinker-Implementierung überschreiben.

let deepLinkerStub = { 
    registerChildNav:() => {} 
}; 

TestBed.configureTestingModule({ 
     ... 
     providers: [ 
     { provide: DeepLinker, useValue: deepLinkerStub }, 
     ... // the usual stuff 

Überprüfen Sie die ursprüngliche Implementierung des DeepLinker, um zu sehen, wie die ursprüngliche registerChildNav arbeitet, und eine Stub-Methode für diesen Test erstellen.

+0

Ich habe meine Frage mit neuer Fehlermeldung aktualisiert. – raj

+0

Dies bedeutet, dass der DeepLinker-Konstruktor 3 Argumente benötigt und diese nicht zur Verfügung gestellt werden. Versuchen Sie, DeepLinker wie folgt bereitzustellen: '{develope: DeepLinker, useValue: {}}', so dass der ursprüngliche Konstruktor gelöscht wird. –

+0

aktualisiert die Antwort –

0

Aktualisieren Sie Ihre Anbieter in test.ts

providers: [ 
    {provide: DeepLinker, useClass: DeepLinkerMock}, 
    {provide: NavController, useClass: NavMock} 

    ...config.providers 
    ], 

und sowie Update Mock.ts zwei Klassen hinzufügen DeepLinkerMock & & NavMock

export class DeepLinkerMock{ 
} 

export class NavMock { 

    public length(): number { 
    return 1; } 

    public push(): any { 
    return new Promise(function(resolve: Function): void { 
     resolve(); 
    }); } 

    public getActive(): any { 
    return { 
     'instance': { 
     'model': 'something', 
     }, 
    }; } 

    public setRoot(): any { 
    return true; } 

    public pop(): any { 
    return new Promise(function(resolve: Function): void { 
     resolve(); 
    }); } 

    public registerChildNav(): any { 
    return new Promise(function(resolve: Function): void { 
     resolve(); 
    }); } 

    public unregisterChildNav(): any { 
    return new Promise(function(resolve: Function): void { 
     resolve(); 
    }); } 

    public popToRoot(): any { 
    return true; } 

    public canGoBack(): any { 
    return true; } } 
2

I wurde das gleiche Problem wie die OP mit der ionischen Starter tabs Vorlage. Ich habe es geschafft, die Komponententests zum Laufen zu bringen, indem ich die Vorschläge hier mit den Beispielen in der mocks.ts, die das Einheitentest-Tutorial zur Verfügung stellt, befolge.

Zuerst verspottet ich die DeepLinker durch eine verspottete Klasse zu den mocks.ts fügte hinzu:

export class DeepLinkerMock { 
} 

Dann fügen Sie es als Anbieter in TestBed.configureTestingModule in test.ts:

{provide: DeepLinker, useClass: DeepLinkerMock}, 

Sie muss auch einen Import für sie hinzufügen, sowie einen Import für das NavMock in test.ts:

An diesem Punkt wird Ihr Test mit this.parent.registerChildNav ist keine Funktion. Ich habe die Signatur der Methode registerChildNav in ionic-angular (Datei nav-controller-base.js) nachgeschlagen. Sie benötigen einen Stub für diese Methode in der Klasse NavMock in mocks.ts hinzuzufügen:

export class NavMock { 
    ... 
    public registerChildNav(nav: any): void { 
     return ; 
    } 
} 

Jetzt Ihren Test ohne Provider für TransitionController scheitern! Dies kann leicht behoben werden, indem dieser Anbieter hinzugefügt wird. An diesem Punkt sieht mein Provider wie folgt aus:

providers: [ 
    App, Form, Keyboard, DomController, MenuController, GestureController, TransitionController, 
    {provide: Platform, useClass: PlatformMock}, 
    {provide: Config, useClass: ConfigMock}, 
    {provide: DeepLinker, useClass: DeepLinkerMock}, 
    {provide: NavController, useClass: NavMock}], 

Hinweis ich den NavController Anbieter mit dem verspotteten ersetzt - was im Tutorial Code existierte aber wurde nicht referenziert. FYI GestureController war auch nicht im ursprünglichen Tutorial-Code - es wird von einer der anderen vier Seiten in den ursprünglichen Starter-Projekt benötigt.

Vergessen Sie nicht, einen Import für den TransitionController (und GestureController) hinzuzufügen. Mein Redakteur (Webstorm) schlug drei Möglichkeiten vor. Ich habe mich für diese eine - nicht sicher, ob es richtig ist:

import {TransitionController} from "ionic-angular/transitions/transition-controller"; 

An diesem Punkt habe ich vier Unit-Tests der Grundform im Tutorial vorgeschlagen Arbeit für die vier Seiten in den Registerkarten Starter. Dies ist die tabs.spec.ts:

import {Component} from "@angular/core"; 

import {HomePage} from "../home/home"; 
import {AboutPage} from "../about/about"; 
import {ContactPage} from "../contact/contact"; 

@Component({ 
    templateUrl: './tabs.html' 
}) 
export class TabsPage { 
    // this tells the tabs component which Pages 
    // should be each tab's root Page 
    tab1Root: any = HomePage; 
    tab2Root: any = AboutPage; 
    tab3Root: any = ContactPage; 

    constructor() { 

    } 
} 

Ich stelle mir vor ich werde dieses Muster folgen, wie ich weiterhin die Verwendung von mehr Teile des Rahmens zu machen, die durch das Tutorial Schriftsteller nicht spotten aus wurden.

+0

Großartig, ich hatte das gleiche Problem. Der einzige Unterschied ist, dass ich eine Dummy-initNav() -Methode für den DeepLinkerMock hinzufügen musste. –

Verwandte Themen