Angular testing router params breaks test bed

后端 未结 3 1296
忘掉有多难
忘掉有多难 2021-02-06 21:58

When I provide params to my TestComponent the test bed blows up if the html contains a [routerLink]

testbed setup



        
相关标签:
3条回答
  • 2021-02-06 22:41

    I figured out the problem/solution.

    We're seeing Cannot read property '_lastPathIndex' of undefined because at one point the Angular router expects a _lastPathIndex property on a snapshot object.

    The relevant part of the Angular source code looks like this:

    if (route.snapshot._lastPathIndex === -1) {
      return new Position(route.snapshot._urlSegment, true, 0);
    }
    

    If snapshot is undefined, it will of course raise the error we're seeing.

    The problem can be solved by making snapshot not-undefined.

    Here's how I did it. My code is a little different from the OP's.

    I have a class called MockActivatedRoute that looks like this.

    export class MockActivatedRoute {
      parent: any;
      params: any;
    
      constructor(options) {
        this.parent = options.parent;
        this.params = options.params;
      }
    }
    

    Here's how I use it in my test.

    let mockActivatedRoute = new MockActivatedRoute({
      parent: new MockActivatedRoute({
        params: Observable.of({ id: '1' })
      })
    });
    

    To make the error go away I just added a snapshot property to MockActivatedRoute.

    export class MockActivatedRoute {
      parent: any;
      params: any;
      snapshot = {};
    
      constructor(options) {
        this.parent = options.parent;
        this.params = options.params;
      }
    }
    
    0 讨论(0)
  • 2021-02-06 22:43

    You can add snapshot property inside your providers array.

    providers: [{ provide: ActivatedRoute, useValue: { snapshot: {} } }]
    
    0 讨论(0)
  • 2021-02-06 22:48

    This works with no errors and no hack

    import {
        TestBed,
        async
    } from '@angular/core/testing';
    import {
        HttpModule,
        BaseRequestOptions,
        Http
    } from '@angular/http';
    import { APP_BASE_HREF } from '@angular/common';
    import {
        RouterModule,
        ActivatedRoute
    } from '@angular/router';
    import { MockBackend } from '@angular/http/testing';
    import { Observable } from 'rxjs';
    import { Component } from '@angular/core';
    fdescribe( 'AppComponent', () => {
        beforeEach( () => {
            TestBed.configureTestingModule( {
                imports      : [
                    HttpModule,
                    RouterModule.forRoot(
                        [
                            {
                                path      : '',
                                component : TestComponent
                            }
                        ] )
                ],
                declarations : [ TestComponent ],
                providers    : [
                    BaseRequestOptions,
                    MockBackend,
                    {
                        provide    : Http,
                        useFactory : function ( backend : MockBackend, defaultOptions : BaseRequestOptions ) {
                            return new Http( backend, defaultOptions );
                        },
                        deps       : [ MockBackend, BaseRequestOptions ]
                    },
                    {
                        provide  : APP_BASE_HREF,
                        useValue : '/'
                    },
                    {
                        provide  : ActivatedRoute,
                        useValue : {
                            params : Observable.of( { versionId : '1' } ),
                            parent : {
                                params : Observable.of( { uniqueId : '1234' } )
                            }
                        }
                    }
                ]
            } );
            TestBed.compileComponents();
        } );
        it( 'should create the app', async( () => {
            let fixture = TestBed.createComponent( TestComponent );
            let app     = fixture.debugElement.componentInstance;
            expect( app ).toBeTruthy();
        } ) );
    } );
    
    @Component( {
        selector    : 'app-root',
        template : `
            <a class="button" [routerLink]="['/']">Back</a>
            <router-outlet></router-outlet>
    
    `,
    } )
    export class TestComponent {
    
    }
    
    0 讨论(0)
提交回复
热议问题