How to mock ActivatedRouteSnapshot when unit testing a Resolver

A. Duff picture A. Duff · Jan 22, 2018 · Viewed 8.6k times · Source

I want to write a unit test for my resolver, which needs to take ActivatedRouteSnapshot in its constructor like so:

export class MyResolver {
  constructor () {
    // ...
  }

  resolve (private route: ActivatedRouteSnapshot) {
    callFoo(route.params.val);
  }
};

But in my unit test, what's the best way to provide an activated route snapshot with mock data? When I try to create an object with just the properties I need, I get an error that it cannot be cast to ActivatedRouteSnapshot:

it('should call foo', inject([MyResolver], async (myResolver: MyResolver) => {
  const mockRoute = {
    params: {
      val: '1234'
    };
  };

  sinon.spy(callFoo);
  myResolver.resolve(mockRoute); // This is the line that errors
  expect(callFoo.calledWith('1234')).to.be.true;
}));

Error:

Type '{ params: { val: string; }; }' cannot be converted to type 'ActivatedRouteSnapshot'.

How can I provide a mock ActivatedRouteSnapshot to pass to my resolver?

Answer

ismaestro picture ismaestro · Jul 3, 2019

You have to provide the active route like this:

import {TestBed} from '@angular/core/testing';
import {SomeResolver} from './some.resolver';
import {ActivatedRoute, convertToParamMap} from '@angular/router';
import {of} from 'rxjs';

describe('SomeResolver', () => {
  let someResolver: SomeResolver;
  let route: ActivatedRoute;

  TestBed.configureTestingModule({
    providers: [
      {
        provide: ActivatedRoute,
        useValue: {snapshot: {paramMap: convertToParamMap({id: 'one-id'})}}
      },
      SomeResolver
    ]
  });

  beforeEach(() => {
    heroResolver = TestBed.get(HeroResolver);
    route = TestBed.get(ActivatedRoute);
  });

  it('should resolve', (() => {
    someResolver.resolve(route.snapshot);
  }));
});

Check a more complex example here.