0
0
AngularHow-ToBeginner · 4 min read

How to Test Routing in Angular: Simple Guide with Examples

To test routing in Angular, import RouterTestingModule in your test module and use Angular's Router service to simulate navigation. Then, verify the current route or component rendering using Jasmine or Jest assertions.
📐

Syntax

Use RouterTestingModule to set up routing in tests. Inject Router and Location to control and check navigation. Use router.navigate() to simulate route changes and fixture.detectChanges() to update the view.

Key parts:

  • RouterTestingModule.withRoutes(routes): sets up routes for testing.
  • router.navigate(['/path']): simulates navigation.
  • location.path(): gets current URL path.
  • fixture.detectChanges(): refreshes component view after navigation.
typescript
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { Component } from '@angular/core';

@Component({ template: '<h1>Home</h1>' })
class HomeComponent {}

@Component({ template: '<h1>About</h1>' })
class AboutComponent {}

const routes = [
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent }
];

describe('Router Test', () => {
  let router: Router;
  let location: Location;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes(routes)],
      declarations: [HomeComponent, AboutComponent]
    });

    router = TestBed.inject(Router);
    location = TestBed.inject(Location);
  });

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

Example

This example shows how to test navigation between two routes and verify the URL changes correctly.

typescript
import { Component } from '@angular/core';
import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';
import { Location } from '@angular/common';

@Component({ template: '<h1>Home</h1>' })
class HomeComponent {}

@Component({ template: '<h1>About</h1>' })
class AboutComponent {}

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
class AppComponent {}

const routes = [
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent }
];

describe('App Routing', () => {
  let router: Router;
  let location: Location;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes(routes)],
      declarations: [AppComponent, HomeComponent, AboutComponent]
    });

    router = TestBed.inject(Router);
    location = TestBed.inject(Location);
    fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
  });

  it('should navigate to /home and display HomeComponent', fakeAsync(() => {
    router.navigate(['/home']);
    tick();
    fixture.detectChanges();
    expect(location.path()).toBe('/home');
    const compiled = fixture.nativeElement as HTMLElement;
    expect(compiled.querySelector('h1')?.textContent).toContain('Home');
  }));

  it('should navigate to /about and display AboutComponent', fakeAsync(() => {
    router.navigate(['/about']);
    tick();
    fixture.detectChanges();
    expect(location.path()).toBe('/about');
    const compiled = fixture.nativeElement as HTMLElement;
    expect(compiled.querySelector('h1')?.textContent).toContain('About');
  }));
});
Output
PASS should navigate to /home and display HomeComponent PASS should navigate to /about and display AboutComponent
⚠️

Common Pitfalls

1. Forgetting to call tick() or fakeAsync: Navigation is asynchronous, so tests must wait for it to complete.

2. Not calling fixture.detectChanges() after navigation: This prevents the view from updating to reflect the new route.

3. Missing route declarations in RouterTestingModule.withRoutes(): Without routes, navigation won't work in tests.

4. Testing navigation without injecting Location: You need Location to verify the current URL path.

typescript
/* Wrong: Missing tick() and detectChanges() */
it('wrong navigation test', () => {
  router.navigate(['/home']);
  expect(location.path()).toBe('/home'); // Fails because navigation is async
});

/* Right: Use fakeAsync, tick(), and detectChanges() */
it('correct navigation test', fakeAsync(() => {
  router.navigate(['/home']);
  tick();
  fixture.detectChanges();
  expect(location.path()).toBe('/home');
}));
📊

Quick Reference

  • Import RouterTestingModule.withRoutes(routes) in your test module.
  • Inject Router and Location to control and check navigation.
  • Use router.navigate(['/path']) inside fakeAsync tests with tick().
  • Call fixture.detectChanges() after navigation to update the view.
  • Verify current URL with location.path() and check rendered components.

Key Takeaways

Always import RouterTestingModule.withRoutes() to set up routes for testing.
Use fakeAsync and tick() to handle asynchronous navigation in tests.
Call fixture.detectChanges() after navigation to update the component view.
Inject Location to verify the current URL path after navigation.
Declare all routes you want to test inside RouterTestingModule.withRoutes().