Search code examples
angularunit-testingjasminekarma-runnertestbed

TestBed TypeError: Cannot read property 'navigate' of undefined


I am trying to perform simple route unit test but

TypeError: Cannot read property 'navigate' of undefined

is thrown.

I am following such tutorial

https://codecraft.tv/courses/angular/unit-testing/routing/

Here is my implemetation:

routes:

export const routes: Routes = [
  {path: '', pathMatch: 'full', redirectTo: 'welcome'},
  {path: 'welcome', component: WelcomeComponent},
  {path: 'offer', loadChildren: () => import('./customer-dashboard/customer-dashboard.module').then(mod => mod.CustomerDashboardModule)},
  {path: 'underConstruction', component: UnderDevelopmentComponent}
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

and unit test:

fdescribe('AppRoutingModule', () => {

    let location: Location;
    let router: Router;
    let fixture;


    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [
                RouterTestingModule.withRoutes(routes),
                WelcomeModule
            ],
            declarations: [
                AppComponent,
            ],
            providers: [
                Location
            ]
        }).compileComponents()
            .then(() => {
                router = TestBed.get(Router);
                location = TestBed.get(Location);
                fixture = TestBed.createComponent(AppComponent);
                router.initialNavigation();
            })

    });

    it('should navigate from empty path to welcome', fakeAsync(() => {
        router.navigate(['']);
        tick();
        expect(location.path()).toBe('/welcome');
    }))

})

Nothing fancy here, this is just basic setup. Looks like TestBed cannot get implementation. Any ideas? To be honest I have the same implementation in my other simple project and it works fine there but here..


Solution

  • Given that compileComponents is an async process, everything in the then section is run after your tests have run.

    Try refactoring to this:

    fdescribe('AppRoutingModule', () => {
    
        let location: Location;
        let router: Router;
        let fixture;
    
    
        beforeEach(async () => {
            await TestBed.configureTestingModule({
                imports: [
                    RouterTestingModule.withRoutes(routes),
                    WelcomeModule
                ],
                declarations: [
                    AppComponent,
                ],
                providers: [
                    Location
                ]
            }).compileComponents();
    
            router = TestBed.get(Router);
            location = TestBed.get(Location);
            fixture = TestBed.createComponent(AppComponent);
            router.initialNavigation();
        });
    
        it('should navigate from empty path to welcome', fakeAsync(() => {
            router.navigate(['']);
            tick();
            expect(location.path()).toBe('/welcome');
        }));
    })