angularunit-testingtestingangular-activatedroute

How to mock ActivatedRoute in Angular without using TestBed


The question is pretty simple. I have never really liked how the original testing works in Angular (the TestBed part), so I have always done it the classic way: mocking with ts-mockito. No TestBed, no configuration needed, zero confusion. I even use Jest instead of Karma/Jasmine.

But when it came to mocking the ActivatedRouter, I always had trouble, as I guess a lot of you out there. One solution I've seen is having an object with the enormous amounts of properties that ActivatedRouter has, and substituting the value of the property you want to mock. That solution is pretty annoying, and quite unsustainable.

The other solution is being forced to use TestBed, which I dont really like, and do the following:

providers: [
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: {
                get: () => 'foo'
              },
              queryParamMap: {
                get: () => 'bar'
              }
            }
          }
        }
      ]

This one is actually pretty good, but as I say it forces you to use TestBed. So, how can you mock ActivatedRoute behaviour without using TestBed?


Solution

  • So, today I figured out a way to mock it in a nice way without having to use TestBed.

    This would be a small example of how a complete test would be using ts-mockito:

    function setup() {
      const route = mock(ActivatedRoute);
      const routeInstance = instance(route);
      Object.defineProperty(routeInstance, 'snapshot', {
        writable: true,
        configurable: true,
        value: {
          paramMap: {
            get: () => 'someParam'
          },
          queryParamMap: {
            get: () => 'someQueryParam'
          }
        }
      });
    
      return {
        sut: new MyComponent(routeInstance),
        route
      };
    }
    
    describe('MyComponent', () => {
      it('should get param and query param from activated route', async () => {
        const { sut, route } = setup();
    
        const actualParam = sut.getParam();
        expect(actualParam).toBe('someParam');
    
        const actualQueryParam = sut.getQueryParam();
        expect(actualQueryParam).toBe('someQueryParam');
      });
    });