How To Test ActivatedRoute paramMap in Angular
Published on August 13, 2024
Last time we talked about how to fix this classic error: NullInjectorError: No provider for ActivatedRoute. We are still in ActivatedRoute land, and today we are talking about how we can test the paramMap method which is a method of ActivatedRoute.
For context this is the code we are trying to test:
payment-option.component.ts
@Component({
selector: 'app-payment-option',
standalone: true,
imports: [],
templateUrl: './payment-option.component.html',
styleUrl: './payment-option.component.scss',
})
export class PaymentOptionComponent implements OnInit {
private _activatedRoute = inject(ActivatedRoute);
ngOnInit(): void {
this._activatedRoute.paramMap.subscribe((params) => {
const id = params.get('id');
if (id) {
this.projectId.set(Number(id));
}
});
}
}
Then let's write our test:
payment-option.compoent.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PaymentOptionComponent } from './payment-option.component';
import { ActivatedRoute, provideRouter } from '@angular/router';
import { homeRoutes } from '../../home.routes';
import { of } from 'rxjs';
describe('PaymentOptionComponent', () => {
let component: PaymentOptionComponent;
let fixture: ComponentFixture<PaymentOptionComponent>;
beforeEach(async () => {
// We would not compile our component and detect changes as we normally do in the beforeEach, because we would override it in other places
TestBed.configureTestingModule({
imports: [PaymentOptionComponent],
providers: [
provideRouter(homeRoutes),
{
provide: ActivatedRoute,
useValue: {
paramMap: of({
get: (key: string) => {
if (key === 'id') {
return '123';
}
return null;
},
}),
},
},
],
});
});
it('should set the projectid based on the parameter id', () => {
// Recreate the component to apply the new mock, and trigger change detection manually
TestBed.compileComponents();
fixture = TestBed.createComponent(PaymentOptionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
// Call the inOnInit method and check to see if the parameter works
component.ngOnInit();
expect(component.projectId()).toBe(123);
});
it('should not set the projectid if the parameter is not `id`', () => {
// Override the mock ActivatedRoute to return a different parameter instead of id, showcasing an instace where a different parameter is in the url
TestBed.overrideProvider(ActivatedRoute, {
useValue: {
paramMap: of({
get: (key: string) => {
if (key) return { name: 'test' };
else return null;
},
}),
},
});
// Recreate the component to apply the new mock, and trigger change detection manually
TestBed.compileComponents();
fixture = TestBed.createComponent(PaymentOptionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
// Call ngOnInit, and confirm that it works as intended when the url parameter is not what you are looking for.
component.ngOnInit();
expect(component.projectId()).toBeNaN();
});
});
That is it, we are done.
Hey 👋, I believe you enjoyed this shortie (it serves as a note to my future self 😎) and learned something new and valuable. Learn about how to test Router.navigate in Angular here.
You can also follow me on Twitter (or instead X 😂) as I share more tips and tricks to make you improve as a better software engineer.
Until then, happy coding!