Angular2 RC5 Mock Activated Route Params

12,599

Solution 1

Your mock must reflect the object it's replacing. You .subscribe because it returns an observable, not just the object, so your mock value should too:

import { Observable } from 'rxjs/Rx';

...

{ provide: ActivatedRoute, useValue: { 'params': Observable.from([{ 'id': 1 }]) } }

Solution 2

Answer given by @jonrsharpe allows you to mock params, but those params would be the same in every test.

If you want to be able to change the params, to set it at the start of a test, you can do it like this:

At the top:

describe('SomeComponent', () => {
  (...)
  let params: Subject<Params>;
  (...)

in beforeEach (the async one - where you have imports, providers etc.):

beforeEach(async(() => {
  params = new Subject<Params>();
  (...)

in providers:

  (...)
  {
    provide: ActivatedRoute,
    useValue: {
      params: params
    }
  }
  (...)

and then in test:

it('someTest', () => {
  params.next({'id': '123'});
  fixture.detectChanges();
  (...)

IMPORTANT NOTE

Be sure to call fixture.detectChanges after params.next.

This means you should remove fixture.detectChanges from beforeEach and add it to every test.

Share:
12,599
GlacialFlames
Author by

GlacialFlames

Updated on June 12, 2022

Comments

  • GlacialFlames
    GlacialFlames almost 2 years

    I need to be able to mock the activated route parameters to be able to test my component.

    Here's my best attempt so far, but it doesn't work.

    { provide: ActivatedRoute, useValue: { params: [ { 'id': 1 } ] } },
    

    The ActivatedRoute is used in the actual component like this:

    this.route.params.subscribe(params => {
        this.stateId = +params['id'];
    
        this.stateService.getState(this.stateId).then(state => {
            this.state = state;
        });
    });
    

    The error I get with my current attempt is simply:

    TypeError: undefined is not a constructor (evaluating 'this.route.params.subscribe')

    Any help would be greatly appreciated.

  • Bhushan Gadekar
    Bhushan Gadekar over 7 years
    Hi i was just wondering How can I use this provide activated route inside my it() block?
  • jonrsharpe
    jonrsharpe over 7 years
    @BhushanGadekar what do you mean? It's just an object, you can assign the useValue to a name.
  • Bhushan Gadekar
    Bhushan Gadekar over 7 years
    @jonsharpe can you edit your answer for it() block.. I have set pageId from route params, and i want to check if after ngOnInit() gets called, my pageId is populated or not?
  • jonrsharpe
    jonrsharpe over 7 years
    @BhushanGadekar you literally just have to extract and name that object within your tests, actually only the inner { 'id': 1 }. You really should be able to figure it out.
  • Magnus Gudmundsson
    Magnus Gudmundsson over 7 years
    This almost works,.... I get cannot read property 'unsubscribe' of undefined. Probably because our Observable goes out of scope. Do you have a solution for that @jonrsharpe ? :)
  • jonrsharpe
    jonrsharpe over 7 years
    @MagnusGud you've given nowhere near enough information to answer that, I don't even know what you're trying to unsubscribe from, or where.
  • Magnus Gudmundsson
    Magnus Gudmundsson over 7 years
    Sorry about that jon. I have the following scenario: in ngOnInit Im doing this: this.subscription = this.route.params.subscribe((params: any) => //and so on. and then in ngOnDestroy Im tearing down the subscription: this.subscription.unsubscribe(); what happens is that subscription is now undefined. I don't really get why. What im going to do is to make my code more robust, and check if subscription is undefined before tearing it down. Then it should work :)
  • jonrsharpe
    jonrsharpe over 7 years
    @MagnusGud I don't know why either, that's probably unrelated to the mocking, as you're getting a real Observable. Once you have isolated the issue, ask a new question with a minimal reproducible example.
  • vince
    vince almost 7 years
    @MagnusGud I have a feeling that you need to add a conditional to your ngOnDestroy() method. Like ngOnDestroy() { if (this.sub) { this.sub.unsubscribe() } }
  • ismaestro
    ismaestro about 4 years
    and if I'm using queryParams inside the snapshot?