Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing a component, which depends on a route param

I have a question about testing a routed component in angular2.

Here is a simple component, which depends on a route with a parameter 'foo'. The attribute foo in the component will be set to the value of the parameter.

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';

@Component({
    selector: 'my-component',
    templateUrl: './my-component.html'
})
export class MyComponent implements OnInit
{
    foo: string;

    constructor(
        private route: ActivatedRoute
    )
    {
    }

    ngOnInit()
    {
        this.route.params.subscribe((params: Params) => {
            this.foo = params['foo'];
        });
    }
}

Now I want to test, that if the component will be created with the route, the param will be set correctly. So somewhere I want to have expect(component.foo).toBe('3');.

import {TestBed, ComponentFixture, async} from '@angular/core/testing';
import {DebugElement} from '@angular/core';
import {By} from '@angular/platform-browser';
import {Params, ActivatedRoute} from '@angular/router';

import {Observable} from 'rxjs';

import {MyComponent} from './MyComponent';

describe('MyComponent', () => {
    let mockParams, mockActivatedRoute;

    let component: MyComponent;
    let fixture: ComponentFixture<MyComponent>;
    let debugElement: DebugElement;
    let element: HTMLElement;

    beforeEach(async(() => {
        mockParams = Observable.of<Params>({foo: '3'});
        mockActivatedRoute = {params: mockParams};

        TestBed.configureTestingModule({
            declarations: [
                MyComponent
            ],
            providers: [
                {provide: ActivatedRoute, useValue: mockActivatedRoute}
            ]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MyComponent);
        component = fixture.componentInstance;

        debugElement = fixture.debugElement;
        element = debugElement.nativeElement;

        fixture.detectChanges();
    });

    it('should set foo to "3"', () => {
        expect(component.foo).toBe('3');
    });
});

My problem is that I don't know how to wait, until resolving of the route is finished, and I can do an expect(). And in this example the test fails and it says "Expected undefined to be '3'.".

Can someone help me please?!

Thank you!

like image 662
be-ndee Avatar asked Feb 22 '17 08:02

be-ndee


People also ask

How do you test ActivatedRoute?

Test Cases for ActivatedRoute it('getDataByNameAndID test case ', () => {route.snapshot.params.id = '2';route.snapshot.params.name = 'testParamChanged';fixture = TestBed. createComponent(MyComponent);component = fixture. componentInstance;fixture. detectChanges();expect(component.name).

How can you capture route parameters?

The first way is through the route snapshot. The route snapshot provides the initial value of the route parameter map (called the paramMap ). You can access the parameters directly without subscribing or adding observable operators. The paramMap provides methods to handle parameter access like get , getAll , and has .

How do you write a unit test case for this router Navigatebyurl?

We write a test case to test the navigating URL. import { ComponentFixture, TestBed, fakeAsync, waitForAsync, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { Router } from '@angular/router'; import { HomeComponent } from './home.

What is Route Param?

Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req.params object, with the name of the route parameter specified in the path as their respective keys.


1 Answers

Okay, reading a little bit in the angular2 testing documentation, I saw their ActivatedRouteStub class. I have created this stub class, and have replaced my original mock with this new class. Now it is working (recognize the line mockActivatedRoute.testParams = {foo: '3'}; in the second beforeEach).

import {TestBed, ComponentFixture, async} from '@angular/core/testing';
import {DebugElement} from '@angular/core';
import {By} from '@angular/platform-browser';
import {Params, ActivatedRoute} from '@angular/router';

import {Observable} from 'rxjs';

import {MyComponent} from './MyComponent';

import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class ActivatedRouteStub
{
    private subject = new BehaviorSubject(this.testParams);
    params = this.subject.asObservable();

    private _testParams: {};
    get testParams() { return this._testParams; }
    set testParams(params: {}) {
        this._testParams = params;
        this.subject.next(params);
    }
}

describe('MyComponent', () => {
    let mockParams, mockActivatedRoute;

    let component: MyComponent;
    let fixture: ComponentFixture<MyComponent>;
    let debugElement: DebugElement;
    let element: HTMLElement;

    beforeEach(async(() => {
        mockActivatedRoute = new ActivatedRouteStub();

        TestBed.configureTestingModule({
            declarations: [
                MyComponent
            ],
            providers: [
                {provide: ActivatedRoute, useValue: mockActivatedRoute}
            ]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MyComponent);
        component = fixture.componentInstance;

        debugElement = fixture.debugElement;
        element = debugElement.nativeElement;

        mockActivatedRoute.testParams = {foo: '3'};

        fixture.detectChanges();
    });

    it('should set foo to "3"', () => {
        expect(component.foo).toBe('3');
    });
});

Do you think this is the right way?

like image 163
be-ndee Avatar answered Sep 28 '22 04:09

be-ndee